使用std::hash以pair为键调用emplace时出现函数不匹配错误
问题根源
C++标准库没有为std::pair<T1, T2>提供默认的std::hash特化,你直接用std::hash<Pair>作为unordered_map的哈希函数模板参数,编译器找不到合法的哈希函数类型,导致整个容器定义无效,最终emplace调用时出现匹配错误。
解决方法
有两种常用方案可以修复这个问题:
方案一:自定义哈希函数结构体
直接定义一个专门用于哈希std::pair<std::string_view, std::string_view>的结构体,代替std::hash<Pair>:
class A { using Pair = std::pair<std::string_view, std::string_view>; // 自定义哈希函数 struct PairHash { size_t operator()(const Pair& p) const { // 组合两个string_view的哈希值,也可以用更均匀的组合逻辑 size_t h1 = std::hash<std::string_view>{}(p.first); size_t h2 = std::hash<std::string_view>{}(p.second); return h1 ^ (h2 << 1); } }; // 使用自定义哈希函数替换原来的MsrPairHash std::unordered_map<Pair, std::shared_ptr<A>, PairHash> mp; public: void foo(std::string_view a, std::string_view b, std::shared_ptr<A> ptr) { mp.emplace(std::make_pair(a, b), std::move(ptr)); // 也可以保持原来的初始化方式:mp.emplace({a, b}, std::move(ptr)); } };
方案二:特化std::hash
在std命名空间内为std::pair<std::string_view, std::string_view>提供std::hash的特化(仅当类型是标准库类型的组合时,这种特化符合标准要求):
// 放在全局作用域或合适的头文件中 namespace std { template<> struct hash<std::pair<std::string_view, std::string_view>> { size_t operator()(const std::pair<std::string_view, std::string_view>& p) const { size_t h1 = hash<std::string_view>{}(p.first); size_t h2 = hash<std::string_view>{}(p.second); // 推荐使用更均匀的哈希组合方式,减少冲突概率 return h1 * 31 + h2; } }; } class A { using Pair = std::pair<std::string_view, std::string_view>; using MsrPairHash = std::hash<Pair>; // 现在特化已存在,可正常使用 std::unordered_map<Pair, std::shared_ptr<A>, MsrPairHash> mp; public: void foo(std::string_view a, std::string_view b, std::shared_ptr<A> ptr) { mp.emplace({a, b}, std::move(ptr)); } };
额外注意事项
使用std::string_view作为unordered_map的键时,必须保证string_view指向的原始字符串生命周期长于unordered_map,否则会出现悬垂引用,导致程序出现未定义行为。
内容的提问来源于stack exchange,提问作者xyf
相关产品推荐
相关产品推荐

