标准中的相关规则说:
over. match.oper#3.4.3
重写后的候选集确定如下:
考虑以下代码:
#include <iostream>
struct Data{
bool operator ==(int c){
return true;
}
};
int main(){
Data d;
bool r = 0 != d; // should be ill-formed
}
我不知道为什么代码可以被编译器编译。IMO,表达式0!=d
的重写候选应该包括表达式x==y的所有非重写候选。我对非重写候选的措辞的理解是,对于操作x!=y,考虑表达式x==y的重写候选之外的任何候选。毕竟,第4个子弹是用来形成重写候选集的。所以,第4个子弹不应该继续适用于已经为原始表达式x!=y
重写的x==y
。在我的例子中,为0重写的候选集!=d
仅包含0==d
的内容,不应考虑d==0
的任何重写候选;
本页中关于不得改写的措辞的相关规则与我的解释相似。(不包括改写的候选人)
对于!=运算符([expr. eq]),重写的候选函数包括表达式x==y的所有成员、非成员和内置候选函数。
不过,继续看下一段,即:
如果通过重载解析为运算符@选择了重写的运算符==候选,则其返回类型应为cv bool,x@y解释为:
既然!=
的重写候选不能继续重写,那它怎么会有一个参数顺序颠倒的合成候选呢?不知道为什么。如何解释!=
重写候选的规则,尤其是非重写候选和最后一条规则的措辞?
我怀疑这是[over. match.oper]/3.4.4授予的:
对于相等运算符,对于表达式y==x的每个非重写候选,重写候选还包括一个合成候选,两个参数的顺序相反。
相等运算符既是运算符==
又是运算符!=
。还要注意,“合成”不是“重写”的同义词:四组候选者是成员候选者、非成员候选者、内置候选者和重写候选者。合成的候选者只属于这些集合中的一个(在本例中是重写候选者的集合)。
因此,我的理解是x!=y
的重写候选者包括两者
x==y
的所有非重写候选者,以及y==x
的非重写候选者合成候选者。所以y==x
的合成候选也是重写的候选。然后[over. match.oper]/9.1开始:
如果@
是!=
并且所选候选者是参数顺序相反的合成候选者,!(y==x)
也就是说,如果选择的重写候选是y==x
的上述合成候选,则结果将是!(y==x)
。