You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#include<compare>enumclassE : int {
Lo = 0,
Hi = 1
};
constexprautooperator<=>(E lhs, E rhs) -> std::strong_ordering {
return (int)rhs <=> (int)lhs;
}
// everybody agrees this is truestatic_assert((E::Lo <=> E::Hi) == std::strong_ordering::greater);
// gcc rejects this, msvc and clang acceptstatic_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.
The text was updated successfully, but these errors were encountered:
jensmaurer
changed the title
[over.match.oper] Spaceship operator doesn't sufficiently suppress builtin-operators
CWG2673 [over.match.oper] Spaceship operator doesn't sufficiently suppress builtin-operators
Jan 1, 2023
Reflector thread: https://lists.isocpp.org/core/2019/10/7407.php
Reference (section label): [over.match.oper]
Issue description:
Consider this example:
The intent here is for the user-provided
operator<=>
to suppress the built-inoperator<=>
forE
. And gcc, clang, and msvc all agree that this does happen... when the comparison expression explicitly usesa <=> 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):When we're evaluating
E::Lo > E::Hi
, the user-providedoperator<=>
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=105200The same thing happens for
operator==
vsoperator!=
. A user-declaredoperator==
will be called fore1 == e2
but not fore1 != 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:clang and msvc already appear to implement it this way.
The text was updated successfully, but these errors were encountered: