为何代码触发编译器错误:指定哈希不满足Hash要求?
unordered_set自定义哈希不满足Hash要求的编译错误解决
问题背景
以下是代码实现:
auto myComp = []( std::array<const string, 3> &a, std::array<const string, 3> &b ) { if ( a[0] == b[0] && a[1] == b[1] && a[2] == b[2] ) { return true; } else { return false; } }; auto myHash = []( std::array<const string, 3> &a ) { return std::hash<std::string>()( a[0] ) ^ std::hash<std::string>()( a[1] ) ^ std::hash<std::string>()( a[2] ); }; std::unordered_set<std::array<const string, 3>, decltype( myHash ), decltype( myComp )> unordSet( 16, myHash, myComp );
编译时触发错误:
MacOSX15.1.sdk/usr/include/c++/v1/__hash_table:607:17 Static assertion failed due to requirement 'integral_constant<bool, false>::value': the specified hash does not meet the Hash requirements
查看哈希检查定义:
#ifndef _LIBCPP_CXX03_LANG template <class _Key, class _Hash> using __check_hash_requirements _LIBCPP_NODEBUG = integral_constant<bool, is_copy_constructible<_Hash>::value && is_move_constructible<_Hash>::value && __invokable_r<size_t, _Hash, _Key const&>::value >; #endif
经排查,__invokable_r<size_t, _Hash, _Key const&>::value条件不满足。
解决方法
1. 修改哈希与比较函数的参数为const引用
unordered_set在调用哈希、比较函数时,会传递const修饰的Key类型,原代码中的lambda参数仅接受非const引用,无法匹配调用要求,这是导致断言失败的核心原因。
修改后的函数如下:
// 相等性比较函数:参数改为const引用 auto myComp = [](const std::array<const std::string, 3>& a, const std::array<const std::string, 3>& b) { return a[0] == b[0] && a[1] == b[1] && a[2] == b[2]; }; // 哈希函数:参数改为const引用 auto myHash = [](const std::array<const std::string, 3>& a) { return std::hash<std::string>()(a[0]) ^ std::hash<std::string>()(a[1]) ^ std::hash<std::string>()(a[2]); };
2. 优化哈希函数(可选但推荐)
原代码使用异或(^)组合哈希值容易引发哈希碰撞(不同元素生成相同哈希值),推荐使用更稳健的组合方式,比如:
auto myHash = [](const std::array<const std::string, 3>& a) { size_t hash_val = std::hash<std::string>()(a[0]); // 用质数乘法分散哈希值,减少碰撞概率 hash_val = hash_val * 31 + std::hash<std::string>()(a[1]); hash_val = hash_val * 17 + std::hash<std::string>()(a[2]); return hash_val; };
3. 完整可编译代码
#include <unordered_set> #include <array> #include <string> #include <functional> int main() { auto myComp = [](const std::array<const std::string, 3>& a, const std::array<const std::string, 3>& b) { return a[0] == b[0] && a[1] == b[1] && a[2] == b[2]; }; auto myHash = [](const std::array<const std::string, 3>& a) { size_t hash_val = std::hash<std::string>()(a[0]); hash_val = hash_val * 31 + std::hash<std::string>()(a[1]); hash_val = hash_val * 17 + std::hash<std::string>()(a[2]); return hash_val; }; std::unordered_set<std::array<const std::string, 3>, decltype(myHash), decltype(myComp)> unordSet(16, myHash, myComp); return 0; }
内容的提问来源于stack exchange,提问作者PkDrew
相关产品推荐
相关产品推荐

