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):
As you can see in the link above, this is the only mention of an implicit default
operator==based onoperator<=>.In your case
operator<=>is notdefaulted, and so the above does not apply.Therefore you need to supply
operator==(or in the general case have it itselfdefaulted if possible based on the operand types).Note:
As @康桓瑋 commented, in your specific case you could actually
defaultedoperator<=>:As explained above, it works because
doubleis converted toJSON, so comparing twoJSONs will invoke thevariant's comparison method.