This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[Accepted as a DR at the February, 2023 meeting.]
Consider:
#include <compare> enum class E : int { Lo = 0, Hi = 1 }; constexpr auto operator<=>(E lhs, E rhs) -> std::strong_ordering { return (int)rhs <=> (int)lhs; } // everybody agrees this is true static_assert((E::Lo <=> E::Hi) == std::strong_ordering::greater); // gcc rejects this, msvc and clang accept static_assert(E::Lo > E::Hi); // #1
The intent here is for the user-provided operator<=> to suppress the built-in operator<=> for E. And gcc, clang, and msvc all agree that this does happen when the comparison expression explicitly uses a <=> b.
But when the comparison expression is a @ b for one of the relational operators, gcc disagrees, conforming to 12.2.2.3 [over.match.oper] bullet 3.3:
For all other operators, the built-in candidates include all of the candidate operator functions defined in 12.5 [over.built] that, compared to the given operator, ... do not have the same parameter-type-list as any non-member candidate that is not a function template specialization.
The issue is that, for #1, the user-provided operator<=> is not a non-member candidate, but a rewritten candidate. A similar situation arises for a user-declared operator==, which will be called for e1 == e2, but not for e1 != e2. Again, clang and MSVC disagree.
Proposed resolution (January, 2023) [SUPERSEDED]:
Change 12.2.2.3 [over.match.oper] bullet 3.3.4 as follows:
Proposed resolution (approved by CWG 2023-02-10):
Change 12.2.2.3 [over.match.oper] bullet 3.3.4 as follows: