提问者:小点点

哪些是!=运算符的重写候选项


标准中的相关规则说:
over. match.oper#3.4.3

重写后的候选集确定如下:

  1. 对于关系([excr. rel])运算符,重写的候选对象包括表达式x的所有未重写的候选对象

考虑以下代码:

#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解释为:

  • 如果@是!=并且选择的候选是参数顺序相反的合成候选,!(y==x),

既然!=的重写候选不能继续重写,那它怎么会有一个参数顺序颠倒的合成候选呢?不知道为什么。如何解释!=重写候选的规则,尤其是非重写候选和最后一条规则的措辞?


共1个答案

匿名用户

我怀疑这是[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)