<concepts>: std::ranges::_Swap::_Use_ADL_swap -- error C2131: expression did not evaluate to a constant
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 11.2k
- Forks
- 1.7k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 22
Description
Describe the bug
Minimal reproduction: https://godbolt.org/z/66jcnWGq8
Code:
#include <map>
#include <ranges>
namespace some_namespace
{
template<typename LEFT_T, typename RIGHT_T>
void swap(LEFT_T && left, RIGHT_T && right)
noexcept(noexcept(std::ranges::swap(std::forward<LEFT_T>(left), std::forward<RIGHT_T>(right))))
{
}
struct Inner
{
};
} // some_namespace
namespace different_namespace
{
template<typename TYPE_T>
struct Outer { };
using SomeTemplate_t = Outer<some_namespace::Inner>;
using MapType_t = std::map < int, SomeTemplate_t >;
void function(void)
{
MapType_t test = {{ 1, SomeTemplate_t()}, { 2, SomeTemplate_t()}, { 3, SomeTemplate_t()}};
[[maybe_unused]] auto const testView = std::views::values(test);
}
} // namespace different_namespace
If you delete the noexcept specification of some_namespace::swap then the example compiles correctly on all three compilers.
https://godbolt.org/z/KTbjhTxdM
Alternatively, if you replace some_namespace::swap with using std::ranges::swap; then it compiles correctly on all three compilers. https://godbolt.org/z/d8cq4YTMe
It seems that somehow std::ranges::_Swap::_Use_ADL_swap is looking into the std::map value type, and instead of recognizing that there is no swap function in namespace different_namespace, it is instead looking into the namespace of the template parameter and seeing that there is a swap function in some_namespace.
Looking at the implementation of _Use_ADL_swap ( https://github.com/microsoft/STL/blob/1bc5ca60fcb41c2ed87a721d6ca2f77844cf6dc6/stl/inc/concepts#L117-L120 ) i don't see anything in the implementation that implies it's trying to look inside of the type's template parameters, just the type itself.
concept _Use_ADL_swap = (_Has_class_or_enum_type<_Ty1> || _Has_class_or_enum_type<_Ty2>)
&& requires(_Ty1&& __t, _Ty2&& __u) {
swap(static_cast<_Ty1&&>(__t), static_cast<_Ty2&&>(__u)); // intentional ADL
};
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the minimal reproduction in the issue and inspect _Use_ADL_swap in stl/inc/concepts around lines 117–120. Compare the behavior with the linked Compiler Explorer examples and determine why the ranges swap check reaches the nested type's namespace; done means the reproduction compiles correctly without removing noexcept or replacing the user-defined swap.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100