-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Reflector thread: https://lists.isocpp.org/core/2019/10/7407.php
Reference (section label): [over.match.oper]
Issue description:
Consider this example:
#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);
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. The wording in [over.match.oper]/3.3 currently says (emphasis mine):
For all other operators, the built-in candidates include all of the candidate operator functions defined in [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.
When we're evaluating E::Lo > E::Hi
, the user-provided operator<=>
isn't a non-member candidate, it's a rewritten candidate, so gcc continues to include the built-in. Patrick Palka makes the same argument in a gcc bug opened for this here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200
The same thing happens for operator==
vs operator!=
. A user-declared operator==
will be called for e1 == e2
but not for e1 != e2
, the latter is specified to call the built-in per the wording (although clang and msvc don't implement it that way).
Suggested resolution:
This seems like an oversight in the adoption of <=>
and the new rewrite rules for ==
, where the wording here did not change. Change /3.3.4 to read:
- do not have the same parameter-type-list as any non-member candidate or rewritten candidate that is not a function template specialization.
clang and msvc already appear to implement it this way.