Consider the following code:
#include <vector>
#include <algorithm>
#include <ranges>
#include <cassert>
// The type is defined in legacy code and we can not change it
struct A
{
int a;
};
bool operator <(const A &a1, const A &a2)
{
return a1.a < a2.a;
}
int main()
{
assert(A {} < A{}); // OK
std::vector<A> c;
assert(std::ranges::is_sorted(c)); // compilation error
}
The code can be fixed by adding the "spaceship" comparison operator to A:
auto operator<=>(const A &) const = default;
However, defining it outside of a class works with the first assert, but not the second:
auto operator <=>(const A &a1, const A &a2) { return a1.a <=> a2.a; }
Is it possible to satisfy the requirements of ranges::less without modifying A?
You need to provide an == as well as <=>. std::ranges::less requires std::totally_ordered not just std::strict_weak_order, so == is also needed. Unless defaulted, <=> doesn't synthesize ==.
#include <vector>
#include <algorithm>
#include <ranges>
#include <cassert>
// The type is defined in legacy code and we can not change it
struct A
{
int a;
};
auto operator <=>(const A &a1, const A &a2) { return a1.a <=> a2.a; }
auto operator ==(const A &a1, const A &a2) { return a1.a == a2.a; }
int main()
{
assert(A {} < A{}); // Comparison exists
std::vector<A> c;
assert(std::ranges::is_sorted(c)); // Comparison exists
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With