std::unordered_map声明执行报错求助:llvm::StringRef哈希问题
解决std::unordered_map使用llvm::StringRef时的哈希错误
这个问题太常见了——llvm::StringRef并没有被标准库的std::hash模板特化,尤其是你用的GCC 4.8这种偏旧的版本,标准库根本不知道怎么计算StringRef的哈希值,所以编译器才会报错说std::hash<llvm::StringRef>是不完整类型。
给你几个靠谱的解决办法:
方法一:用LLVM自带的哈希映射容器(最推荐)
LLVM专门为自家类型做了适配的哈希容器,比如llvm::StringMap或者通用的llvm::DenseMap,完全不用操心哈希函数的问题:
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/DenseMap.h" // 用StringMap嵌套的写法 llvm::StringMap<llvm::StringMap<struct IntRel>> BinaryRel; // 或者用DenseMap(StringRef适配良好,无需额外配置) llvm::DenseMap<llvm::StringRef, llvm::DenseMap<llvm::StringRef, struct IntRel>> BinaryRel;
LLVM的容器对自家类型兼容性拉满,性能也适配LLVM的使用场景,优先选这个准没错。
方法二:为std::hash手动特化llvm::StringRef
如果你一定要用标准库的std::unordered_map,可以给std::hash<llvm::StringRef>加个特化实现,记得放在std命名空间下:
#include <unordered_map> #include "llvm/ADT/StringRef.h" namespace std { template<> struct hash<llvm::StringRef> { size_t operator()(const llvm::StringRef& sr) const { // 直接复用LLVM的哈希计算函数 return llvm::hash_value(sr); } }; } // 现在就能正常使用标准库的unordered_map了 std::unordered_map<llvm::StringRef, std::unordered_map<llvm::StringRef, struct IntRel>> BinaryRel;
这种特化是符合C++标准的(针对用户自定义类型的特化),注意别在多个文件重复定义就行。
方法三:声明时显式指定自定义哈希函数
不想污染std命名空间的话,可以在创建std::unordered_map时直接传入哈希函数对象:
#include <unordered_map> #include "llvm/ADT/StringRef.h" // 定义哈希函数结构体 struct StringRefHash { size_t operator()(const llvm::StringRef& sr) const { return llvm::hash_value(sr); } }; // 声明容器时指定哈希类型 std::unordered_map<llvm::StringRef, std::unordered_map<llvm::StringRef, struct IntRel>, StringRefHash> BinaryRel;
这种方式更灵活,适合只在局部使用该容器的场景。
另外提一句,GCC 4.8确实有点老了,要是条件允许升级到GCC 7+,能避免不少这类兼容性问题,不过上面的方法在GCC 4.8下都能正常跑。
内容的提问来源于stack exchange,提问作者R.Omar
相关产品推荐
相关产品推荐

