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

Fed*_*dor 7 c++ overloading conversion-operator language-lawyer overload-resolution

在下面的程序中 structS提供了两个转换运算符: indouble和 in long long int。然后一个类型的对象S被传递给一个函数f,重载为floatand 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 );
}
Run Code Online (Sandbox Code Playgroud)

MSVC 编译器可以正常接受程序,并选择f( double )重载。f然而,GCC 和 Clang 都发现, demo的调用存在歧义:https: //gcc.godbolt.org/z/5csd5dfYz

看来MSVC在这里是对的,因为转换: operator long long int()->f( float )不是提升。这是错的吗?

有一个类似的问题Overload conventions with multiple function and multiple conversionoperators,但其中有一个升级案例,并且现在所有编译器都同意,与这个问题中的情况不同。

son*_*yao 5

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

[over.ics.rank]/3 :

(强调我的)

相同形式的两个隐式转换序列是不可区分的转换序列,除非适用以下规则之一:

...

(3.3) 用户定义的转换序列 U1 是比另一个用户定义的转换序列 U2 更好的转换序列,如果它们包含相同的用户定义的转换函数或构造函数,或者它们在聚合初始化中初始化相同的类,并且在任何一种情况下都是第二个U1的标准转换序列优于U2的第二标准转换序列。

用户定义的转换序列涉及两个不同的用户定义的转换函数(operator double()operator long long int()),因此编译器无法选择其中之一;不考虑第二个标准转换顺序。