std::unordered_map
中的密钥为boost::uuids::uuid
,因此128位哈希值被视为唯一。但是,编译器无法知道,因此说明了这一点。
error C2338: The C++ Standard doesn't provide a hash for this type.
如何让地图将密钥用作哈希值?顺便说一句,std::size_t
在我的系统中被定义为unsigned int __w64
,我认为它只涉及64位。
答案 0 :(得分:2)
即使此映射是标识,您始终需要提供将键映射到散列值的函数对象。您可以为std::hash<boost::uuids::uuid>
定义专门化并让std::unordered_map<K, V>
自动选择此项,也可以使用函数对象类型的附加模板参数来参数化无序映射。除了哈希之外,还需要使用相等操作,但默认情况下,使用operator==()
可能没问题。
也就是说,除非您的系统具有内置的128位整数类型,否则哈希值将不接受128位整数。哈希值必须是std::size_t
才能与标准无序容器一起使用。 std::hash<T>
专业化的完整要求列表在20.8.12 [unord.hash]中列出:
std::hash<X>
需要默认可构造,可复制构造,并可复制可分配。std::hash<X>
需要可以更换。argument_type
,并为散列值的类型提供result_type
,后者与std::size_t
相同。k1 == k2
=&gt; h(k1) == h(k2)
必须为h
是散列函数对象。因此,您需要按照以下方式定义:
namespace std {
template <>
struct hash<boost::uuids::uuid>
{
typedef boost::uuids::uuid argument_type;
typedef std::size_t result_type;
std::size_t operator()(boost::uuid::uuid key) const {
return transform_to_size_t(key);
}
};
}
其中transform_to_size_t()
是您需要提供的实际转化。
};
答案 1 :(得分:1)
您需要为类型boost::uuids::uuid
提供哈希函数。由于它是唯一的,您可以使用stl标识。
这是unordered_map的声明。
template < class Key, // unordered_map::key_type
class T, // unordered_map::mapped_type
class Hash = hash<Key>, // unordered_map::hasher
class Pred = equal_to<Key>, // unordered_map::key_equal
class Alloc = allocator< pair<const Key,T> > // unordered_map::allocator_type
> class unordered_map;
答案 2 :(得分:0)
我认为最简单的方法是为这些类型实现std::hash
的特化,返回相同的输入:
namespace std
{
template<>
struct hash<Foo>
{
Foo operator(const Foo& foo)
{
return foo;
}
};
}
假设示例中的类型Foo
可隐式转换为std::size_t
。
在您的情况下,类型是128位GUID,std::size_t
使用32位或64位。您可以将64位GUID拆分为64/32位的部分,并组合这些值。
答案 3 :(得分:0)
我发现没有办法使用UUID作为std::unordered_map
的密钥,因为UUID是128位长,而地图的哈希是std::size_t
,只能容纳64位。
相反,我删除了真正的128位UUID,只有64位ID,可以存储在uint64_t
类型中,并且标准库的容器本身支持。