为什么 operator!= 对于许多标准库类型在 C++20 中被删除?
Why is operator!= removed in C++20 for many standard library types?
根据 cppreference,std::type_info::operator!=
在 C++20 中被删除,但是,std::type_info::operator==
显然仍然存在。
背后的原因是什么?我可能同意比较不平等是没有意义的,但是比较平等也同样毫无意义,不是吗?
同样,许多其他标准库类型的 operator!=
,包括 std::unordered_map::operator!=
and std::unordered_set::operator!=
等容器将根据 cppreference 在 C++20 中删除。
与if(id1 != id2)
相比,必须编写if(!(id1 == id2))
并不能使任何代码更清晰,相反,恰恰相反...
我们不再需要 operator!=
提供的库。提供 operator==
允许编译器根据 a == b
自行进行一些杂耍和评估 a != b
。
[over.match.oper]
3 For a unary operator @ with an operand of a type whose
cv-unqualified version is T1, and for a binary operator @ with a left
operand of a type whose cv-unqualified version is T1 and a right
operand of a type whose cv-unqualified version is T2, four sets of
candidate functions, designated member candidates, non-member
candidates, built-in candidates, and rewritten candidates, are
constructed as follows:
3.4.3 For the != operator ([expr.eq]), the rewritten candidates
include all non-rewritten candidates for the expression x == y.
std::type_info
和更多库类型的 operator!=
作为 P1614 - The Mothership has Landed.
的一部分被删除
在 C++20 中,关系运算符的工作方式发生了变化,特别是引入了宇宙飞船 <=>
运算符。特别是,如果您只提供 operator==
,那么 a != b
将被重写为 !(a == b)
。
The rewritten candidate set is determined as follows:
- For the relational ([expr.rel]) operators, the rewritten candidates include all non-rewritten candidates for the expression x <=> y.
- For the relational ([expr.rel]) and three-way comparison ([expr.spaceship]) operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expression y <=> x.
- For the != operator ([expr.eq]), the rewritten candidates include all non-rewritten candidates for the expression x == y.
- For the equality operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expression y == x.
- For all other operators, the rewritten candidate set is empty.
If a rewritten operator== candidate is selected by overload resolution for an operator @, its return type shall be cv bool, and x @ y is interpreted as:
- if @ is != and the selected candidate is a synthesized candidate with reversed order of parameters, !(y == x),
- otherwise, if @ is !=, !(x == y),
- otherwise (when @ is ==), y == x,
in each case using the selected rewritten operator== candidate.
因此,不再需要 operator!=
的显式重载。删除运算符并没有改变比较语义。
据我所知,所有容器的 operator!=
都被移除了(检查例如 the vector synopsis)。唯一的例外是容器适配器 std::queue
和 std::stack
:我猜这是为了在与第三方容器一起使用时保持向后兼容性,以防相等运算符不对称。
根据 cppreference,std::type_info::operator!=
在 C++20 中被删除,但是,std::type_info::operator==
显然仍然存在。
背后的原因是什么?我可能同意比较不平等是没有意义的,但是比较平等也同样毫无意义,不是吗?
同样,许多其他标准库类型的 operator!=
,包括 std::unordered_map::operator!=
and std::unordered_set::operator!=
等容器将根据 cppreference 在 C++20 中删除。
与if(id1 != id2)
相比,必须编写if(!(id1 == id2))
并不能使任何代码更清晰,相反,恰恰相反...
我们不再需要 operator!=
提供的库。提供 operator==
允许编译器根据 a == b
自行进行一些杂耍和评估 a != b
。
[over.match.oper]
3 For a unary operator @ with an operand of a type whose cv-unqualified version is T1, and for a binary operator @ with a left operand of a type whose cv-unqualified version is T1 and a right operand of a type whose cv-unqualified version is T2, four sets of candidate functions, designated member candidates, non-member candidates, built-in candidates, and rewritten candidates, are constructed as follows:
3.4.3 For the != operator ([expr.eq]), the rewritten candidates include all non-rewritten candidates for the expression x == y.
std::type_info
和更多库类型的 operator!=
作为 P1614 - The Mothership has Landed.
在 C++20 中,关系运算符的工作方式发生了变化,特别是引入了宇宙飞船 <=>
运算符。特别是,如果您只提供 operator==
,那么 a != b
将被重写为 !(a == b)
。
The rewritten candidate set is determined as follows:
- For the relational ([expr.rel]) operators, the rewritten candidates include all non-rewritten candidates for the expression x <=> y.
- For the relational ([expr.rel]) and three-way comparison ([expr.spaceship]) operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expression y <=> x.
- For the != operator ([expr.eq]), the rewritten candidates include all non-rewritten candidates for the expression x == y.
- For the equality operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expression y == x.
- For all other operators, the rewritten candidate set is empty.
If a rewritten operator== candidate is selected by overload resolution for an operator @, its return type shall be cv bool, and x @ y is interpreted as:
- if @ is != and the selected candidate is a synthesized candidate with reversed order of parameters, !(y == x),
- otherwise, if @ is !=, !(x == y),
- otherwise (when @ is ==), y == x,
in each case using the selected rewritten operator== candidate.
因此,不再需要 operator!=
的显式重载。删除运算符并没有改变比较语义。
据我所知,所有容器的 operator!=
都被移除了(检查例如 the vector synopsis)。唯一的例外是容器适配器 std::queue
和 std::stack
:我猜这是为了在与第三方容器一起使用时保持向后兼容性,以防相等运算符不对称。