使用std::pair<ndmInst*, bool>作为std::unordered_map键编译错误求助
解决std::unordered_map编译错误的思路
问题代码
// 注意:cmpClkgate类定义在unordered_map实例化之后,顺序错误 std::unordered_map<std::pair<ndmInst*, bool>, std::vector<slmEndpointsTimingInfo>, cmpClkgate> clkgateEndpointsMap; slmEndpointsTimingInfo endpointsInfoObj; std::pair<ndmInst*, bool> p = std::make_pair(clkFaninInsts[0], isFallEdgeClk); clkgateEndpointsMap[p].push_back(endpointsInfoObj); //slmPMUEPAsgnStrgy.cc:125 class cmpClkgate { public: bool operator()(const std::pair<ndmInst*, bool>& p1, const std::pair<ndmInst*, bool>& p2) const { // this slmPMUEPAsgnStrgy.cc:81 if (p1.first != p2.first) { return p1.first < p2.first; } return p1.second < p2.second; } };
编译错误信息
/depotbld/RHEL7.0/gcc-9.5.0/include/c++/9.5.0/bits/hashtable_policy.h: In instantiation of ‘std::__detail::_Hash_code_base<...>’: ... /depotbld/RHEL7.0/gcc-9.5.0/include/c++/9.5.0/bits/hashtable_policy.h:1382:16: error: static assertion failed: hash function must be invocable with an argument of key type 1382 | static_assert(__is_invocable<const _H1&, const _Key&>{}, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /depotbld/RHEL7.0/gcc-9.5.0/include/c++/9.5.0/bits/hashtable_policy.h:1384:16: error: no match for call to ‘(const dc::cmpClkgate) (const std::pair<ndmInst*, bool>&)’ 1384 | return _M_h1()(__k); | ~~~~~~~^~~~~ slmPMUEPAsgnStrgy.cc:81:8: note: candidate: ‘bool dc::cmpClkgate::operator()(const std::pair<ndmInst*, bool>&, const std::pair<ndmInst*, bool>&) const’ 81 | bool operator()(const std::pair<ndmInst*, bool>& p1, const std::pair<ndmInst*, bool>& p2) const { | ^~~~~~~~ slmPMUEPAsgnStrgy.cc:81:8: note: candidate expects 2 arguments, 1 provided
错误原因分析
- 模板参数类型混淆:
std::unordered_map的第三个模板参数要求是哈希函数(Hash),该函数需要接受单个Key类型参数,返回size_t类型的哈希值;但你传入的cmpClkgate是一个二元比较函数(用于判断两个键的大小/相等性,是std::map的第三个参数类型),它的operator()需要两个参数,完全不符合哈希函数的要求。 - 类定义顺序错误:
cmpClkgate类的定义在unordered_map实例化之后,编译器在实例化时无法识别该类型,这也是潜在问题。
解决方案
步骤1:定义正确的哈希函数
针对std::pair<ndmInst*, bool>类型,实现一个哈希函数类,将pair的两个成员的哈希值组合起来:
struct HashClkgateKey { size_t operator()(const std::pair<ndmInst*, bool>& key) const { // 分别计算指针和bool的哈希值,再组合避免冲突 size_t hash1 = std::hash<ndmInst*>()(key.first); size_t hash2 = std::hash<bool>()(key.second); return hash1 ^ (hash2 << 1); } };
步骤2:调整unordered_map的模板参数
std::unordered_map的第四个参数是相等判断函数(Pred),把cmpClkgate放到这个位置(若默认的std::equal_to<std::pair<...>>能满足需求,也可省略)。同时确保类的定义在实例化之前:
// 先定义哈希函数和比较函数 struct HashClkgateKey { size_t operator()(const std::pair<ndmInst*, bool>& key) const { size_t hash1 = std::hash<ndmInst*>()(key.first); size_t hash2 = std::hash<bool>()(key.second); return hash1 ^ (hash2 << 1); } }; class cmpClkgate { public: bool operator()(const std::pair<ndmInst*, bool>& p1, const std::pair<ndmInst*, bool>& p2) const { if (p1.first != p2.first) { return p1.first < p2.first; } return p1.second < p2.second; } }; // 实例化unordered_map:第三个参数是哈希函数,第四个是相等判断函数 std::unordered_map<std::pair<ndmInst*, bool>, std::vector<slmEndpointsTimingInfo>, HashClkgateKey, cmpClkgate> clkgateEndpointsMap;
步骤3:验证相等判断函数的必要性
如果你的相等判断逻辑和std::pair默认的相等判断(两个成员分别相等)一致,可省略第四个参数,直接使用默认实现:
std::unordered_map<std::pair<ndmInst*, bool>, std::vector<slmEndpointsTimingInfo>, HashClkgateKey> clkgateEndpointsMap;
额外注意事项
- 哈希函数的设计要尽量减少冲突,上面的移位异或只是简单实现,也可以用
hash1 * 31 + hash2这类更稳定的组合方式。 std::hash对指针的实现是直接取地址的哈希值,一般可满足需求。
内容的提问来源于stack exchange,提问作者chhatna
相关产品推荐
相关产品推荐

