升级到最新的Visual Studio 2022版本17.6后,我们的一个自定义视图停止被识别为std::ranges::range
。结果发现问题出在视图的迭代器中同时存在operator ==
和operator !=
。
请在下面找到最小的简化示例(已经没有视图和迭代器):
struct A {
friend bool operator ==( const A &, const A & ) = default;
};
struct B {
friend bool operator ==( const B &, const B & ) = default;
friend bool operator ==( const B &, const A & ) { return false; }
// Visual Studio 2022 version 17.6 does not like next line
friend bool operator !=( const B &, const A & ) { return true; }
};
template< class T, class U >
concept comparable =
requires(const std::remove_reference_t<T>& t,
const std::remove_reference_t<U>& u) {
{ t == u } -> std::same_as<bool>;
{ t != u } -> std::same_as<bool>;
{ u == t } -> std::same_as<bool>;
{ u != t } -> std::same_as<bool>;
};
// ok in GCC, Clang and Visual Studio before version 17.6
static_assert( comparable<A, B> );
GCC和Clang接受该示例,但不接受最新的Visual Studio,它会打印错误:
<source>(25): error C2607: static assertion failed
<source>(25): note: the concept 'comparable<A,B>' evaluated to false
<source>(18): note: 'bool operator ==(const B &,const A &)': rewritten candidate function was excluded from overload resolution because a corresponding operator!= declared in the same scope
<source>(4): note: could be 'bool operator ==(const A &,const A &)' [found using argument-dependent lookup]
<source>(8): note: or 'bool operator ==(const B &,const B &)' [found using argument-dependent lookup]
<source>(9): note: or 'bool operator ==(const B &,const A &)' [found using argument-dependent lookup]
<source>(4): note: or 'bool operator ==(const A &,const A &)' [synthesized expression 'y == x']
<source>(8): note: or 'bool operator ==(const B &,const B &)' [synthesized expression 'y == x']
<source>(9): note: or 'bool operator ==(const B &,const A &)' [synthesized expression 'y == x']
<source>(18): note: 'bool operator ==(const B &,const A &)': rewritten candidate function was excluded from overload resolution because a corresponding operator!= declared in the same scope
<source>(18): note: while trying to match the argument list '(const A, const B)'
在线演示:https://gcc.godbolt.org/z/evTfofq3d
这是新的Visual Studio编译器中的一个错误,还是相反,其他人错了?
1条答案
按热度按时间4sup72z81#
这里潜在的问题似乎与不同的编译器如何处理ADL(参数相关查找)和重载解析有关。
您提供的重载将在多个操作符声明可见的上下文中使用(由于ADL规则)。有趣的是,这会导致歧义,不同的编译器会以不同的方式解决。
在匹配运算符时,版本17.6似乎比GCC、Clang和Visual Studio的早期版本有更严格的解释!=和operator==。
所以,回答你的问题,错误可能是由于编译器错误,或者它可能是由于更严格的遵守C++标准在较新版本的Visual Studio。如果没有std::ranges::range的完整规范以及它如何与operator交互,很难确定!=和operator==。
也许,一个可能的解决方法是定义操作符!=在运算符==方面对于A和B: