Before C++20 | After C++20 |
---|---|
class MyInt {
int value = 0;
public:
friend bool operator==(MyInt a, MyInt b) {
return a.value == b.value;
}
friend bool operator!=(MyInt a, MyInt b) {
return !(a == b);
}
friend bool operator<(MyInt a, MyInt b) {
return a.value < b.value;
}
friend bool operator<=(MyInt a, MyInt b) {
return !(b < a);
}
friend bool operator>(MyInt a, MyInt b) {
return b < a;
}
friend bool operator>=(MyInt a, MyInt b) {
return !(a < b);
}
}; |
class MyInt {
int value = 0;
public:
auto operator<=>(MyInt) const = default;
}; |
C++20 introduces the three-way comparison operator, also known as the "spaceship operator":
class Person {
std::string lastname;
std::string firstname;
public:
auto operator<=>(Person const&) const = default;
};
The spaceship operator behaves similarly to strcmp
and memcmp
:
strcmp /memcmp |
operator<=> |
Meaning |
---|---|---|
if (strcmp(a, b) < 0); |
if (auto cmp = a <=> b; cmp < 0); |
If |
if (strcmp(a, b) > 0); |
if (auto cmp = a <=> b; cmp > 0); |
If |
if (strcmp(a, b) == 0); |
if (auto cmp = a <=> b; cmp == 0); |
If |
Thanks to Symmetry for Spaceship [P0905],
if a <=> b
is well-formed, then b <=> a
is also well-formed. This
means only one definition of operator<=>
is required to provide
heterogeneous type comparison (it does not need to be a (friend
-ed)
non-member function).
Existing equality and comparison operator overloads take precedence over the spaceship operator. This means this is not a breaking change, and users can still specialize particular operators as desired.
Note
The spaceship operator resembles a TIE bomber
<=>
, not a TIE fighter|=|
.
C++20 also introduces comparison categories to specify regarding weak/partial/strong ordering and weak/strong equality.
Before C++20 | After C++20 |
---|---|
template <typename T>
class LinkedList<T>::iterator {
Node<T>* ptr = nullptr;
public:
friend bool operator==(iterator const& other) {
return ptr == other.ptr;
}
friend bool operator!=(iterator const& other) {
return ptr != other.ptr;
}
}; |
template <typename T>
class LinkedList<T>::iterator {
Node<T>* ptr = nullptr;
public:
std::strong_equality operator<=>(iterator const&) const = default;
}; |
Comparison categories implicitly convert to corresponding AS-IF
categories, e.g. std::strong_ordering
implies/is implicitly
convertible to std::strong_equality
and std::weak_ordering
.
Note
Descriptions and examples heavily reference the original paper, Consistent Comparison [P0515].