作者:yu2531958135 | 来源:互联网 | 2024-12-16 11:10
C++标准文档中对运算符重写的具体规则进行了详细说明,特别是针对 != 运算符的处理。根据over.match.oper#3.4.3
部分的规定,重写候选集的确定遵循以下原则:
1. 对于关系运算符(如 <、>、<=、>=),重写候选集包括表达式 x <=> y
的所有未重写候选。
2. 对于关系和三路比较运算符,还包括参数顺序颠倒的合成候选,即 y <=> x
。
3. 对于 != 运算符,重写候选集包括表达式 x == y
的所有未重写候选。
4. 对于等式运算符,对于每个未重写的候选 y == x
,还包括一个参数顺序颠倒的合成候选。
5. 对于其他运算符,重写候选集为空。
考虑以下示例代码:
#include
struct Data {
bool operator==(int c) {
return true;
}
};
int main() {
Data d;
bool r = 0 != d; // 应该是非法的
}
尽管从直觉上看,这段代码应该无法编译,因为它尝试使用 Data
类型的对象与整数进行 != 运算,但实际编译器却能成功编译这段代码。这里的关键在于,对于 != 运算符,重写候选集不仅包括 x == y
的所有未重写候选,还包括 y == x
的合成候选。
标准文档进一步指出,对于 != 运算符,重写候选集包括 x == y
的所有成员、非成员和内置候选。这意味着即使 Data
类定义了 operator==
,编译器也会考虑 0 == d
和 d == 0
的情况。
此外,标准还规定,如果通过重载决议选择了重写的 operator==
候选者,且该候选者是一个合成候选(即参数顺序颠倒的候选),则 x != y
将被解释为 !(y == x)
。
因此,对于 0 != d
,编译器会首先考虑 0 == d
和 d == 0
的重写候选,如果找到合适的候选者,则 0 != d
将被解释为 !(d == 0)
。这解释了为什么代码能够编译成功。