如何直接使用密钥作为std::unordereded_map的散列
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位。您可以将128位的GUID拆分为64/32位的部分,然后组合这些值。
我找不到将UUID用作std::unordered_map
的密钥的方法,因为UUID是128位长,而映射的哈希是只能容纳64位的std::size_t
。
相反,我只删除了64位ID的实际128位UUID,这些ID可以存储在uint64_t
类型中,并且由标准库的容器本地支持。
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 使用一个考虑到std::map中键值的滚动或换行的键
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 允许从 std::map 的密钥窃取资源?
- 有没有办法对std::unordered_set、std::unrdered_map、std::set、std::map
- 将重物插入std::map
- 使用通用值初始化 std::map,不重复
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- C++:当所有条目都保证是唯一时,替代 std::map
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- 使用字符数组作为 Map 中的键
- C++如何创建 std::map
- C++ equivalent to Java Map getOrDefault?
- 从其他容器中移动构造"std::map"
- 如何使用 uint64_t 键类型从 std::map<int, std::string> 返回值?
- 将 std::map::emplace 与返回 shared_ptr 的函数一起使用是否正确?
- C++中 std::map 的运行时复杂度是多少?
- 为什么在 std::map 上移动无法将元素从一个映射移动到另一个映射