编译器报错:std::variant作为unordered_map键无operator==匹配
问题原因及修复方案
核心问题1:operator==未声明为const成员函数
你的A和B类中定义的operator==不是const成员函数,而std::variant在执行相等比较时,会以const对象的身份调用内部类型的operator==,这导致编译器找不到匹配的const版本相等运算符,从而报错。
修复方法:给A和B的operator==加上const修饰,同时建议参数改用const引用避免拷贝:
// A类的operator==修改后 bool operator==(const A& a) const { return a.s == this->s; } // B类的operator==修改后 bool operator==(const B& b) const { return b.i == this->i; }
核心问题2:std::variant<A,B>缺少hash特化(C++17及以下)
std::unordered_map要求键类型同时满足可哈希和可比较相等。你只特化了A和B的std::hash,但C++17及更早标准中,std::hash并没有默认支持std::variant,需要手动特化:
namespace std { template<> struct hash<std::variant<A,B>> { size_t operator()(const std::variant<A,B>& v) const { return std::visit([](const auto& val) { return std::hash<std::decay_t<decltype(val)>>{}(val); }, v); } }; }
如果你的编译器支持C++20及以上,std::hash已默认支持std::variant(前提是所有备选类型都有对应的std::hash特化,你这里已满足),这一步可省略。
完整修复后的代码
#include <variant> #include <string> #include <unordered_map> #include <functional> // 用于std::visit struct Base { public: virtual std::size_t get_hash() const = 0; }; struct A : public Base { std::string s; public: A(std::string str): s{str} {} std::size_t get_hash() const override { return std::hash<std::string>{}(this->s); } bool operator==(const A& a) const { return a.s == this->s; } }; struct B : public Base { int i; public: B(int it): i{it} {} std::size_t get_hash() const override { return std::hash<int>{}(this->i); } bool operator==(const B& b) const { return b.i == this->i; } }; namespace std { template<> struct hash<A> { size_t operator()(const A& a) const { return a.get_hash(); } }; template<> struct hash<B> { size_t operator()(const B& b) const { return b.get_hash(); } }; // C++17需要手动特化variant的hash,C++20可省略 template<> struct hash<std::variant<A,B>> { size_t operator()(const std::variant<A,B>& v) const { return std::visit([](const auto& val) { return std::hash<std::decay_t<decltype(val)>>{}(val); }, v); } }; } int main(int argc, char* argv[]) { std::unordered_map<std::variant<A,B>, int> map; std::variant<A,B> key1{A("hi")}; std::variant<A,B> key2{B(1)}; map.insert({key1, 1}); map.insert({key2, 2}); }
内容的提问来源于stack exchange,提问作者julian
相关产品推荐
相关产品推荐

