C++ 中的重载函数和多个转换运算符歧义,编译器不同意

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

在下面的程序中,struct S提供了两个转换运算符:in double和in long long int。然后将类型为 S 的对象传递给函数 f,为 floatdouble 重载:

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 编译器可以很好地接受程序,选择 f( double ) 重载。然而,GCC 和 Clang 在 f 的调用中都发现了歧义,演示:https://gcc.godbolt.org/z/5csd5dfYz

似乎MSVC就在这里,因为转换: operator long long int() -> f( float ) 不是促销。有错吗?

有一个类似的问题,但是里面有一个promotion case,现在所有的编译器都同意,不像这个问题中的case。

GCC 和 Clang 是正确的。隐式转换序列(用户定义的转换序列)是无法区分的。

[over.ics.rank]/3:

(强调我的)

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.

用户定义的转换序列涉及两个不同的用户定义转换函数(operator double()operator long long int()),因此编译器不能select一个;不考虑第二个标准转换序列。