[英]How to directly use key as hash for std::unordered_map?
我的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位整数。 哈希值需要是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
=> 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()
是您需要提供的实际转换。 };
你需要为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位。 您可以将64位GUID拆分为64/32位的部分,并组合这些值。
我发现无法使用UUID作为std::unordered_map
键,因为UUID是128位长,而映射的散列是std::size_t
,它只能容纳64位。
相反,我只删除了64位ID的真实128位UUID,它们可以存储在uint64_t
类型中,并且本身由标准库的容器支持。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.