Why is this an issue?
Comparison operators like ==
or <=>
, despite being not hard to write, remain a source of bugs as they need to be
updated with every change in the class’s member list. For instance, if a newly introduced member in the class is not considered by the operation, the
issue will only manifest if two instances are identical, except for the newly introduced member. As a consequence, this type of bug is usually hard to
spot.
C++20 introduced the ability to define both operator<=>
and operator==
as defaulted (= default
) to
indicate that they should consider all members in the order of their declaration. This not only makes code concise but also makes all the comparison
operators resilient to the changes to the list of members. Thanks to operator rewriting, all other comparison operations (!=
,
<
, >
, <=
, =>
) can also rely on these robust operators.
Furthermore, when operator<=>
is defined as defaulted, the compiler will generate a defaulted version of operator==
if no other version is declared.
This rule raises an issue when the implementation of operator<=>
or operator==
has an equivalent semantic to the
defaulted implementation.
Noncompliant code example
struct Comparable {
int x;
int y;
};
bool operator==(const Comparable& lhs, const Comparable& rhs) { // Noncompliant
return lhs.x == rhs.x && lhs.y == rhs.y;
}
struct Ordered {
int x;
int y;
};
bool operator==(const Ordered& lhs, const Ordered& rhs) { // Noncompliant
return lhs.x == rhs.x && lhs.y == rhs.y;
}
auto operator<=>(const Ordered& lhs, const Ordered& rhs) { // Noncompliant
if (res = lhs.x <=> rhs.x; res != 0)
return x;
return lhs.y <=> rhs.y;
}
Compliant solution
struct Comparable {
int x;
int y;
friend bool operator==(const Comparable&, const Comparable&) = default;
};
struct Ordered {
int x;
int y;
friend auto operator<=>(const Ordered&, const Ordered&) = default;
};
Resources
- {rule:cpp:S6186} - removing redundant comparison operators
- {rule:cpp:S6187} - replacing multiple comparison operators with
operator<=>