my 中的键std::unordered_map
是boost::uuids::uuid
s,因此 128 位散列被认为是唯一的。但是,编译器无法知道这一点,因此会这样说。
error C2338: The C++ Standard doesn't provide a hash for this type.
如何使地图按原样使用键作为哈希?顺便说一句,在我的系统上std::size_t
定义unsigned int __w64
,我认为它仅指 64 位。
my 中的键std::unordered_map
是boost::uuids::uuid
s,因此 128 位散列被认为是唯一的。但是,编译器无法知道这一点,因此会这样说。
error C2338: The C++ Standard doesn't provide a hash for this type.
如何使地图按原样使用键作为哈希?顺便说一句,在我的系统上std::size_t
定义unsigned int __w64
,我认为它仅指 64 位。
即使此映射是身份,您也始终需要提供将键映射到哈希值的函数对象。您可以定义一个专业化std::hash<boost::uuids::uuid>
并std::unordered_map<K, V>
自动选择它,或者您可以使用函数对象类型的附加模板参数参数化无序映射。除了哈希之外,还需要一个相等操作,但默认情况下,使用operator==()
可能是可以的。
也就是说,哈希值不会接受 128 位整数,除非您的系统具有内置的 128 位整数类型。哈希值必须是 astd::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
=>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()
您需要提供的实际转换在哪里。};
您需要为 type 提供哈希函数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;
我认为最简单的方法是实现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 位。您可以将 128 位 GUID 拆分为 64/32 位的一部分,然后组合这些值。
我发现没有办法使用 UUID 作为键,std::unordered_map
因为 UUID 的长度为 128 位,而映射的散列std::size_t
只能容纳 64 位。
相反,我删除了真正的 128 位 UUID,仅用于 64 位 id,这些 id 可以存储在uint64_t
类型中,并且由标准库的容器原生支持。