I'm trying my luck with the spaceship operator. Say I have a variant-like object (that I conveninently derive from std::variant
with fixed template parameters) and I want to define operators ==, <, >, !=, etc... for easy comparison, I thought I could just spaceship-it according to the contained type and have the compiler define all operators by itself:
#include <compare>
#include <iostream>
#include <variant>
#include <string>
class JSON : public std::variant<std::monostate, double, std::string> {
public:
using variant::variant;
auto operator<=>(std::string str) const {
return std::get<std::string>(*this) <=> str;
}
auto operator<=>(double d) const {
return std::get<double>(*this) <=> d;
}
};
int main()
{
JSON myjson = 2.3;
if (myjson == 2.3) {
std::cout << "JSON was 2.3" << std::endl;
}
}
Yet this apporach yields:
<source>: In function 'int main()':
<source>:22:16: error: no match for 'operator==' (operand types are 'JSON' and 'double')
22 | if (myjson == 2.3) {
| ~~~~~~ ^~ ~~~
| | |
| JSON double
I would have thought that the compiler now knows how to write operator==
for my variant object in case rhs is a double or rhs is a string. In case the variant contains a different alternative, I'm fine with std::get throwing at me.
From Default comparisons (since C++20):
Per the rules for any operator<=> overload, a defaulted <=> overload > will also allow the type to be compared with <, <=, >, and >=.
If operator<=> is defaulted and operator== is not declared at all, then operator== is implicitly defaulted.
As you can see in the link above, this is the only mention of an implicit default operator==
based on operator<=>
.
In your case operator<=>
is not default
ed, and so the above does not apply.
Therefore you need to supply operator==
(or in the general case have it itself default
ed if possible based on the operand types).
Note:
As @康桓瑋 commented, in your specific case you could actually default
ed operator<=>
:
auto operator<=>(const JSON& d) const = default;
As explained above, it works because double
is converted to JSON
, so comparing two JSON
s will invoke the variant
's comparison method.