In C++20, the <=>
(spaceship) operator can return four possible values:
std::strong_ordering::less
std::strong_ordering::equal
std::strong_ordering::greater
std::strong_ordering::equivalent
Understanding the difference between equal
and equivalent
is crucial for certain comparisons.
std::strong_ordering::equal
This result is returned when two values are exactly the same. For instance, two integers with the same value or two strings that match exactly.
std::strong_ordering::equivalent
This result indicates that two values are considered equal in terms of ordering, but not necessarily identical. This can be useful in situations where you want to treat different representations as equivalent.
For example, case-insensitive string comparison or comparing pointers that point to the same object but have different addresses.
Here’s an example with a custom string class that uses case-insensitive comparison:
#include <cctype>
#include <compare>
#include <iostream>
#include <string>
class CaseInsensitiveString {
public:
std::string Value;
std::strong_ordering operator<=>(
const CaseInsensitiveString& Other) const {
auto it1 = Value.begin();
auto it2 = Other.Value.begin();
while (it1 != Value.end()
&& it2 != Other.Value.end()
) {
char c1 = std::tolower(*it1);
char c2 = std::tolower(*it2);
if (c1 < c2)
return std::strong_ordering::less;
if (c1 > c2)
return std::strong_ordering::greater;
++it1;
++it2;
}
if (Value.size() < Other.Value.size())
return std::strong_ordering::less;
if (Value.size() > Other.Value.size())
return std::strong_ordering::greater;
return std::strong_ordering::equivalent;
}
bool operator==(
const CaseInsensitiveString& Other) const {
return std::equal(
Value.begin(), Value.end(),
Other.Value.begin(), Other.Value.end(),
[](char a, char b) {
return std::tolower(a) == std::tolower(b);
});
}
};
int main() {
CaseInsensitiveString A{"hello"};
CaseInsensitiveString B{"HELLO"};
if (A == B) {
std::cout << "A is equal to B\n";
}
if ((A <=> B) == std::strong_ordering::equivalent) {
std::cout << "A is equivalent to B\n";
}
}
A is equal to B
A is equivalent to B
In this example, A
and B
are considered both equal and equivalent due to the case-insensitive comparison. The distinction between equal
and equivalent
allows for nuanced comparison logic in custom types.
Answers to questions are automatically generated and may not have been reviewed.
A guide to simplifying our comparison operators using C++20 features