While trying out the new Tie-Interceptor three-way comparison operator <=>
I was wondering what would be an example such that
struct Foo {
/*
....
*/
auto operator<=>(const Foo &rhs) const = default;
};
would lead to a compiler error with
Foo Bar1;
Foo Bar2;
std::strong_ordering(Bar1 <=> Bar2);
but not with
Foo Bar1;
Foo Bar2;
std::weak_ordering(Bar1 <=> Bar2);
What would be an example for Foo
? In other words how would Foo
not imply substitutability?
I know that I could write my own implementation of the operator which returns std::weak_ordering ... less/greater/equivalent
but how to force the compiler to do so?
I've read Practical meaning of strong_ordering and weak_ordering among others so far.
... but how to force the compiler to do so?
When you use auto
as the return type of defaulted operator<=>
, the compiler will pick the common comparison category of all the members. So if you have something like:
// any type that is weakly ordered
struct Weak {
bool operator==(Weak const&) const;
std::weak_ordering operator<=>(Weak const&) const;
};
struct Foo {
Weak w;
int i;
auto operator<=>(Foo const&) const = default;
};
Then using <=>
on two instances of type Foo
will give you a weak_ordering
, since that's the common comparison category of Weak
and int
.
In the same way that given:
struct Bar {
float f;
auto operator<=>(Bar const&) const = default;
};
Bar::operator<=>
gives you a std::partial_ordering
.
There are no core language types that give you a std::weak_ordering
, but there are some library types that might:
// some typical C++17 comparable type
struct Widget {
bool operator==(Widget const&) const;
bool operator<(Widget const&) const;
};
struct LotsOfWidgets {
std::vector<Widget> widgets;
auto operator<=>(LotsOfWidgets const&) const = default;
};
The <=>
here returns std::weak_ordering
(to avoid having to assume what it is you meant by <
and ==
).
Or you could simply provide that yourself. You don't have to use auto
:
struct WeakInt {
int i;
friend std::weak_ordering operator<=>(WeakInt, WeakInt) = default;
};