通过太空船运算符让编译器自动生成==、<、>等比较运算符的问题
解决C++太空船运算符无法自动生成跨类型
operator==的问题 问题原因
C++20的太空船运算符(<=>)仅会在同类比较场景下自动生成对应的operator==:即当你为类定义了与自身类型的operator<=>(无论是= default还是自定义实现),编译器才会自动推导生成同类的相等性运算符。而你定义的是JSON与double、std::string的跨类型operator<=>,这类场景下编译器不会自动生成对应的operator==,这就是编译报错的核心原因。
解决方案
根据你希望保留“类型不匹配时std::get抛出异常”的需求,提供两种可行方案:
方案1:手动实现跨类型operator==
直接为JSON类补充与double、std::string的相等性判断重载,和已有的<=>配对:
#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; } // 补充对应的相等性运算符 bool operator==(std::string str) const { return std::get<std::string>(*this) == str; } bool 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; } }
该方案完全保留你原本的逻辑:当JSON存储的类型与比较参数不匹配时,std::get会抛出std::bad_variant_access异常。
方案2:复用std::variant的默认比较逻辑
如果你希望避免直接调用std::get,可以将double/std::string转换为JSON对象,复用std::variant自带的比较运算符:
#include <compare> #include <iostream> #include <variant> #include <string> class JSON : public std::variant<std::monostate, double, std::string> { public: using variant::variant; // 继承std::variant的默认比较运算符 using variant::operator<=>>; using variant::operator==; // 跨类型比较重载,转换为同类后复用默认逻辑 auto operator<=>(double d) const { return *this <=> JSON{d}; } auto operator<=>(std::string str) const { return *this <=> JSON{str}; } bool operator==(double d) const { return *this == JSON{d}; } bool operator==(std::string str) const { return *this == JSON{str}; } }; int main() { JSON myjson = 2.3; if (myjson == 2.3) { std::cout << "JSON was 2.3" << std::endl; } }
注意:该方案中,当JSON存储的类型与比较参数不匹配时,会直接返回false而非抛出异常。如果需要异常逻辑,仍建议使用方案1。
内容的提问来源于stack exchange,提问作者glades
相关产品推荐
相关产品推荐

