为什么对于许多标准库类型在C ++ 20中删除了operator!=?


44

根据cppreferencestd::type_info::operator!=被C ++ 20删除,但是std::type_info::operator==显然仍然存在。

背后的原因是什么?我可能同意比较不平等是没有意义的,但是比较相等也同样是没有意义的,不是吗?

同样,operator!=在许多其他标准库类型中,包括容器,例如std::unordered_map::operator!=和,std::unordered_set::operator!=将根据cppreference在C ++ 20中将其删除。

相比之下,必须编写if(!(id1 == id2))并不会使任何代码更清晰if(id1 != id2),相反,相反……

Answers:


62

在C ++ 20中,关系运算符的工作方式发生了变化,特别是在引入了宇宙飞船<=>运算符之后。特别是,如果仅提供operator==,则将a != b被重写为!(a == b)

来自[over.match.oper] /3.4

重写的候选集确定如下:

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

[over.match.oper] / 9

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

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

在每种情况下,都使用选定的重写运算符==候选。

因此,operator!=不再需要显式的重载。删除运算符并没有更改比较语义。

operator!=据我所知,所有容器都已被移除(例如检查矢量概要)。唯一的例外是容器适配器std::queuestd::stack:我的猜测是,如果与相等的容器不对称,则当与第三方容器一起使用时,它将保留向后兼容性。


7
p1614也可能引起关注,因为我认为这是消除超载的建议。
N. Shead

39

我们不再需要提供图书馆operator!=。提供operator==让编译器做一些杂耍和评估a != b来讲a == b,都在它自己的。

[over.match.oper]

3对于一元运算符@,其操作数的类型为cv不合格的版本为T1,对于二元运算符@,其左操作数的类型为cv不合格的版本为T1,而右运算符的类型为cv-不合格版本为T2,按以下方式构造四组候选函数,指定成员候选,非成员候选,内置候选和重写候选:

3.4.3对于!=运算符([expr.eq]),重写的候选对象包括表达式x == y的所有未重写的候选对象。

std::type_infooperator!=作为P1614的一部分,删除了更多的库类型-“母舰降落”

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.