CWG Issue 2673 (original) (raw)

This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118f. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-11-07


2673. User-declared spaceship vs. built-in operators

Section: 12.2.2.3 [over.match.oper]Status: C++23Submitter: Barry RevzinDate: 2022-12-30

[Accepted as a DR at the February, 2023 meeting.]

Consider:

#include

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: