如何将两个64位数值作为std::unordered_map的键并实现哈希?
实现两个64位数值作为std::unordered_map的键
1. 定义键类型
首先把两个64位数值封装成结构体,作为整体键使用,确保任意一个位变化都会产生不同的键:
#include <cstdint> #include <unordered_map> struct RenderPipelineKey { uint64_t renderState; uint64_t pipelineState; // 重载==运算符,用于哈希表判断键是否相等 bool operator==(const RenderPipelineKey& other) const noexcept { return renderState == other.renderState && pipelineState == other.pipelineState; } };
2. 实现高效哈希函数(无需循环)
以下几种方法都不需要循环16次,基于位运算或编译器内置逻辑实现高效哈希:
方法1:组合std::hash结果
利用标准库对uint64_t的哈希支持,通过移位、异或组合两个哈希值:
namespace std { template<> struct hash<RenderPipelineKey> { size_t operator()(const RenderPipelineKey& key) const noexcept { auto hashRender = hash<uint64_t>{}(key.renderState); auto hashPipeline = hash<uint64_t>{}(key.pipelineState); // 64位系统下直接移位异或,32位系统拆分64位值组合 if constexpr (sizeof(size_t) == 8) { return hashRender ^ (hashPipeline << 32 | hashPipeline >> 32); } else { uint32_t pipeLow = static_cast<uint32_t>(key.pipelineState); uint32_t pipeHigh = static_cast<uint32_t>(key.pipelineState >> 32); return hashRender ^ (pipeLow ^ (pipeHigh << 16)); } } }; }
方法2:使用编译器内置哈希合并函数
GCC/Clang可直接用__builtin_hash_combine,MSVC可自行实现类似逻辑,底层都是高效位运算:
namespace std { template<> struct hash<RenderPipelineKey> { size_t operator()(const RenderPipelineKey& key) const noexcept { size_t seed = hash<uint64_t>{}(key.renderState); __builtin_hash_combine(seed, key.pipelineState); return seed; } }; }
方法3:用std::pair简化(C++20及以上)
C++20标准库已为std::pair提供哈希特化,可直接用std::pair<uint64_t, uint64_t>作为键,省去自定义结构体:
// 直接使用pair作为键 std::unordered_map<std::pair<uint64_t, uint64_t>, YourValueType> stateMap;
3. 哈希表的使用示例
定义好键和哈希后,即可正常操作std::unordered_map:
// 假设值类型为渲染资源指针 std::unordered_map<RenderPipelineKey, RenderResource*> stateCache; // 添加元素 RenderPipelineKey key{0x123456789ABCDEF0, 0xFEDCBA9876543210}; stateCache[key] = new RenderResource(); // 查询元素 auto it = stateCache.find(key); if (it != stateCache.end()) { // 使用it->second访问对应资源 }
额外优化:用128位整数作为键
如果追求极致简洁,可将两个64位值拼接为__int128,手动实现其哈希逻辑:
namespace std { template<> struct hash<__int128> { size_t operator()(__int128 val) const noexcept { uint64_t low = static_cast<uint64_t>(val); uint64_t high = static_cast<uint64_t>(val >> 64); return hash<uint64_t>{}(low) ^ (hash<uint64_t>{}(high) << 1); } }; } // 生成128位键 __int128 makeKey(uint64_t renderState, uint64_t pipelineState) { return (static_cast<__int128>(renderState) << 64) | pipelineState; } // 使用哈希表 std::unordered_map<__int128, RenderResource*> stateCache;
内容的提问来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

