In C++20 the way that the relational operators work was changed, notably with the introduction of the spaceship <=>
operator. In particular, If you only provide operator==
, then a != b
is rewritten to !(a == b)
.
From [over.match.oper]/3.4:
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.
And [over.match.oper]/9:
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.
As such, an explicit overload for operator!=
is no longer necessary. The removal of the operator has not changed comparison semantics.
All containers have had their operator!=
removed, as far as I can tell (check e.g. the vector synopsis). The only exceptions are the container adaptors std::queue
and std::stack
: my guess is that it is to preserve backwards compatibility when used with third-party containers, in case the equality operators are not symmetric.