为自定义Vec2实现带max参数的哈希函数时unordered_map报错
自定义带参数哈希函数适配std::unordered_map的问题解决
错误原因分析
- 模板参数类型不匹配:
std::unordered_map的第三个模板参数要求是哈希函数的类型,但你直接传入了HashVec2int{300}(一个对象实例),编译器因此报错"expected a type, got 'HashVec2int{300u}'"。 - 哈希函数与key类型不匹配:你的
unordered_map的key是std::pair<iVec2, iVec2>,但HashVec2int的operator()仅支持Vec2<int>类型,无法处理pair对象,导致后续operator[]调用失败。 - 哈希结构体构造函数未启用:你注释掉了
HashVec2int的构造函数,无法正确初始化maximum成员变量。
修正方案
- 启用
HashVec2int的构造函数,确保能传入并保存maximum参数。 - 针对
std::pair<iVec2, iVec2>类型实现哈希函数,内部复用HashVec2int来分别哈希两个Vec2成员,再合并哈希值。 - 在创建
unordered_map时,模板参数填写哈希函数类型,通过构造函数传入带参数的哈希实例。
修正后的完整代码
#include <iostream> #include <unordered_map> #include <utility> #include <stdint.h> template <class T> struct Vec2 { T x, y; Vec2() : x(0) , y(0) { }; Vec2(T xn, T yn) : x(xn), y(yn) { }; bool operator==(const Vec2& vec) const { return (x == vec.x) && (y == vec.y); } }; struct HashVec2int { const uint32_t maximum; // 启用构造函数,初始化maximum参数 HashVec2int(uint32_t m) : maximum(m) { } std::size_t operator()(const Vec2<int>& vec) const { // 转换为std::size_t避免溢出 return static_cast<std::size_t>(vec.x) * maximum + vec.y; } }; // 针对std::pair<iVec2, iVec2>的哈希函数 struct HashPairVec2 { HashVec2int vec_hash; // 传入max_x参数,初始化内部的HashVec2int HashPairVec2(uint32_t max_x) : vec_hash(max_x) {} std::size_t operator()(const std::pair<Vec2<int>, Vec2<int>>& p) const { // 合并两个Vec2的哈希值,使用质数31来减少哈希碰撞 std::size_t h1 = vec_hash(p.first); std::size_t h2 = vec_hash(p.second); return h1 * 31 + h2; } }; int main() { using iVec2 = Vec2<int>; // 模板参数填哈希类型HashPairVec2,构造时传入带参数的哈希实例 std::unordered_map<std::pair<iVec2, iVec2>, float, HashPairVec2> umap{HashPairVec2(300)}; umap[std::make_pair(iVec2(1, 2), iVec2(2, 3))] = 3.14f; std::cout << umap[std::make_pair(iVec2(1, 2), iVec2(2, 3))]; return 0; }
额外说明
- 如果你的实际需求是将单个
Vec2<int>作为unordered_map的key,只需调整unordered_map的模板参数和构造方式:std::unordered_map<iVec2, float, HashVec2int> umap{HashVec2int(300)}; - 合并哈希值时使用质数(如31、101)是为了降低哈希碰撞的概率,你可以根据实际场景调整。
内容的提问来源于stack exchange,提问作者gournge
相关产品推荐
相关产品推荐

