After upgrading to latest Visual Studio 2022 version 17.6, one of our custom views stopped to be recognized as std::ranges::range. It turned out that the problem was in the presence of both operator == and operator != in the view's iterator.
Please find below minimal simplified example (without views and iterators already):
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> );
The example is accepted by GCC and Clang, but not the latest Visual Studio, which prints the error:
<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)'
Online demo: https://gcc.godbolt.org/z/evTfofq3d
Is it a bug in new Visual Studio compiler, or on the contrary the others are wrong?
For equality operator expressions x == y and x != y, a synthesized candidate with the order of the two parameters reversed is added for each member, non-member, and built-in operator==s found, unless there is a matching operator!=.so maybe that's being interpreted as==(const B &,const A &)isn't generated because!=( const B &, const A & )isn't present?