c++language-lawyeroverloadingoverload-resolutionconversion-operator

Overloaded function and multiple conversion operators ambiguity in C++, compilers disagree


In the following program struct S provides two conversion operators: in double and in long long int. Then an object of type S is passed to a function f, overloaded for float and double:

struct S {
    operator double() { return 3; }
    operator long long int() { return 4; }
};

void f( double ) {}
void f( float ) {}

int main() {
    S s;
    f( s );
}

MSVC compiler accepts the program fine, selecting f( double ) overload. However both GCC and Clang see an ambiguity in the calling of f, demo: https://gcc.godbolt.org/z/5csd5dfYz

It seems that MSVC is right here, because the conversion: operator long long int() -> f( float ) is not a promotion. Is it wrong?

There is a similar question Overload resolution with multiple functions and multiple conversion operators, but there is a promotion case in it and all compilers agree now, unlike the case in this question.


Solution

  • GCC and Clang are correct. The implicit conversion sequences (user-defined conversion sequences) are indistinguishable.

    [over.ics.rank]/3:

    (emphasis mine)

    Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of the following rules applies:

    ...

    (3.3) User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor or they initialize the same class in an aggregate initialization and in either case the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2.

    The user-defined conversion sequences involves two different user-defined conversion functions (operator double() and operator long long int()), so compilers can't select one; the 2nd standard conversion sequence won't be considered.