cplusplus / CWG

Core Working Group
23 stars 7 forks source link

[over.match.best] Implementations have divergence for the ambiguity between two rewritten candidates sourced from the same one #392

Closed xmh0511 closed 1 year ago

xmh0511 commented 1 year ago

Full name of submitter (unless configured in github; will be published with the issue): Jim X

Consider this example:

#include <iostream>
struct A
{
    int a;
    auto operator <=>(const A& other)
    {
        return a <=> other.a;
    }
};

int main()
{
    A x{ 1 };
    A y{ 1 };
    auto r = x < y;
}

For the relation operator <, [over.match.oper] p3.4.1 says:

For the relational ([expr.rel]) operators, the rewritten candidates include all non-rewritten candidates for the expression x <=> y.

[over.match.oper] p3.4.2 says:

For the relational ([expr.rel]) and three-way comparison ([expr.spaceship]) operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expression y <=> x.

That is, the candidates are:

auto A::operator<=>(A&, const A&) // rewritten candidate for x < y, named F1
auto A::operator<=>(A&, const A&) // reversed rewritten candidate for y<=>x, named F2

Even though such two rewritten candidates are sourced from the same one, however, [over.match.best.general] p2.9 explicitly says:

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2...

  • F1 and F2 are rewritten candidates, and F2 is a synthesized candidate with reversed order of parameters and F1 is not

That means, F1 trumps F2 anyway when F1 and F2 are both viable candidates. However, Clang says:

:15:16: error: ISO C++20 considers use of overloaded operator '<' (with operand types 'A' and 'A') to be ambiguous despite there being a unique best viable function [-Werror,-Wambiguous-reversed-operator]

GCC says:

:15:18: error: C++20 says that these are ambiguous, even though the second is reversed:

If I didn't miss something, it seems there is no wording in the current standard that says so. https://godbolt.org/z/1faqzTEE3

xmh0511 commented 1 year ago

y <=> x finds auto operator <=>(A&, const A&), so the reversed version is auto operator <=>(const A&, A&)

For the first argument, from x to A& and x to const A&, the ICS of F1 trumps F2, for the second argument, from x to const A& and x to A&, the ICS of F2 trumps F1, so there are ambiguous.