赋值表达式没有歧义,这是有道理的。但我不明白为什么关系表达式确实有。
#include <iostream>
class MyClass {
public:
operator int() { return 0; }
operator unsigned int() { return 1u; }
};
int main()
{
MyClass obj;
std::cout << (obj == 0); // ambiguity
unsigned int n = obj; // no ambiguity
}
unsigned int n = obj
不是赋值表达式,它不使用任何赋值,内置或重载。
它是初始化,只是通过对
MyClass
中的转换函数执行重载解析来初始化对象,为要初始化的类型选择最佳匹配的函数。
obj == 0
是一个表达式,重载解析应用于operator==
(不是转换函数!),以确定==
是否应解释为内置比较运算符或是否应调用operator==
重载定义在某处。
在此重载决策中,内置运算符
==
由一些想象的重载声明表示
bool operator==(L, R);
对于每对类型
L
和 R
,其中每个类型要么是浮点类型,要么是提升的整数类型。 (还有枚举类型、指针类型、成员指针类型等的进一步重载,这些在这里并不重要。)
特别是还有候选人
bool operator==(int, int);
和
bool operator==(unsigned int, int);
这两种方法都可以通过使用
MyClass
转换函数的用户定义转换来实现(并且都不需要对返回值进行任何进一步转换)。因此,它们在两个参数上都具有完全相同的隐式转换等级。
重载决策中没有任何决定因素可以消除其中一个候选者比另一个更好的歧义,因此重载决策是不明确的。
事实上,如果不同候选者对参数上的隐式转换序列使用不同的转换函数,则无论是否需要任何进一步的转换,这两个隐式转换序列始终被认为是不明确的。