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

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

重写的候选集确定如下:

  1. 对于关系 ([expr.rel]) 运算符,重写的候选项包括表达式 x <=> y 的所有未重写的候选项。
  2. 对于关系([expr.rel])和三路比较([expr.spaceship])算子,重写的候选者还包括一个合成的候选者,两个参数的顺序颠倒了,对于每个未重写的候选者表达式 y <=> x。
  3. 对于 != 运算符 ([expr.eq]),重写的候选项包括表达式 x == y 的所有未重写的候选项
  4. 对于等式运算符,对于表达式 y == x 的每个未重写候选,重写候选还包括一个合成候选,两个参数的顺序颠倒。
  5. 对于所有其他算子,重写的候选集为空。

考虑以下代码:

#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 用于形成重写的候选集。因此,第四项不应继续适用于x==y已为原始表达式重写的x!=y。在我的例子中,重写的候选集0!=d只包含 for 0==d,它不应该考虑任何重写的候选d==0

本页中有关非重写措辞的相关规则与我的解释类似。(不包括改写的候选人)

对于 != 运算符 ([expr.eq]),重写的候选项包括表达式 x == y 的所有成员、非成员和内置候选项

不过,继续看下一段,那就是:

如果通过重载决议为 operator@ 选择了重写的 operator== 候选者,则其返回类型应为 cv bool,并且 x@y 被解释为:

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

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

回答

我怀疑这是由[over.match.oper]/3.4.4授予的:

对于等式运算符,对于表达式 y == x 的每个未重写候选,重写候选还包括一个合成候选,两个参数的顺序颠倒。

平等运营商 operator==operator!=。还要注意“综合”不是“重写”的同义词:四组候选是成员候选非成员候选内置候选重写候选。合成候选仅属于这些集合中的一个(在这种情况下是重写候选的集合)。

因此,我的理解是重写的候选对象x != y包括

  • 的所有未重写候选者x == y,以及
  • 的非重写候选的合成候选y == x

所以合成的候选者y == x也是重写的候选者。然后[over.match.oper]/9.1开始:

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

也就是说,如果选择的重写候选是上面合成的候选y == x,那么结果将是!(y == x)


以上是哪些是!=运算符的重写候选者的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>