C++20 introduced the new spaceship operator <=> which allows for synthesizing equality and comparison operators based on the strength of the ordering of the three-way comparison.
However, it appears that when working with following simple toy example performing a heterogeneous comparison, it is unable to synthesize equality operators -- but is still succeeds to synthesize ordering operators -- despite having std::strong_ordering:
#include <compare>
#include <cassert>
template <typename T>
struct Wrapper {
int value;
auto operator<=>(const Wrapper&) const = default;
template <typename U>
auto operator<=>(const Wrapper<U>& other) const {
return value <=> other.value;
}
};
void test() {
// Same type equality -- works
assert(Wrapper<Foo>{42} == Wrapper<Foo>{42});
// Heterogeneous comparison -- works
assert(Wrapper<Foo>{42} < Wrapper<Bar>{45});
// Heterogeneous equality -- doesn't work?
assert(Wrapper<Foo>{42} == Wrapper<Bar>{42});
}
On GCC, this gives the following error:
<source>: In function 'void test()':
<source>:26:29: error: no match for 'operator==' (operand types are 'Wrapper<Foo>' and 'Wrapper<Bar>')
26 | assert(Wrapper<Foo>{42} == Wrapper<Bar>{42});
| ~~~~~~~~~~~~~~~~ ^~ ~~~~~~~~~~~~~~~~
| | |
| Wrapper<Foo> Wrapper<Bar>
From what I can tell from cppreference, the automatic synthesized operators for a strongly-ordered <=> should include equality -- but yet this doesn't seem to be the case with heterogeneous comparisons, but it is for homogeneous comparisons.
This fails on gcc, clang, and even MSVC -- so I am pretty sure this is the correct behavior, albeit unexpected. I know this can be fixed by defining a custom operator== as well, but my question is mostly why this happens in the first place, and what can I expect to be generated from a heterogeneous operator<=> definition?