【问题标题】:Why is operator!= removed in C++20 for many standard library types?为什么 operator!= 在 C++20 中为许多标准库类型删除?
【发布时间】:2020-02-07 17:20:41
【问题描述】:
【问题讨论】:
标签:
c++
c++-standard-library
comparison-operators
c++20
equality-operator
【解决方案1】:
在 C++20 中,关系运算符的工作方式发生了变化,特别是引入了 spaceship <=> 运算符。特别是,如果您只提供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:
如果通过重载决议为运算符@选择了重写的运算符==候选,则其返回类型应为cv bool,x@y解释为:
- 如果 @ 是 != 并且所选候选者是参数顺序相反的合成候选者,!(y == x),
-
否则,如果 @ 是 !=, !(x == y),
- 否则(当 @ 为 == 时),y == x,
在每种情况下使用选定的重写运算符== 候选。
因此,operator!= 不再需要显式重载。运算符的移除并没有改变比较语义。
据我所知,所有容器的operator!= 都已删除(例如the vector synopsis)。唯一的例外是容器适配器std::queue 和std::stack:我的猜测是它在与第三方容器一起使用时保持向后兼容性,以防相等运算符不对称。
【讨论】:
-
p1614 可能也很有趣,因为我相信这是删除重载的提议。
【解决方案2】:
我们不再需要operator!= 提供的库。提供operator== 允许编译器根据a == b 进行一些杂耍和评估a != b,这一切都靠它自己。
[over.match.oper]
3 对于一元运算符@,其操作数的类型为
cv-unqualified 版本是 T1,对于二元运算符 @ 带有左
其 cv 非限定版本为 T1 的类型的操作数和一个权限
其 cv 非限定版本为 T2 的类型的操作数,四组
候选人职能、指定成员候选人、非成员
候选者、内置候选者和重写候选者,是
构造如下:
3.4.3 对于 != 运算符 ([expr.eq]),重写的候选项
包括表达式 x == y 的所有未重写候选。
std::type_info 和更多库类型的operator!= 作为P1614 - The Mothership has Landed 的一部分被删除。