【发布时间】:2014-08-13 06:06:56
【问题描述】:
问题
什么是 std::hash 的良好特化,可用于 std::unordered_map 或 std::unordered_set 的第三个模板参数,用于所有成员数据类型都已具有良好特化 std:: 的用户定义类型哈希?
对于这个问题,我将“好”定义为易于实现和理解、相当高效且不太可能产生哈希表冲突。良好的定义不包括任何关于安全的陈述。
Google 的现状
目前,有两个 StackOverflow 问题是 Google 搜索“std hash specialization”的首选。
第一个,How to specialize std::hash::operator() for user-defined type in unordered containers?,说明打开 std 命名空间和添加模板特化是否合法。
第二个How to specialize std::hash for type from other library 基本上解决了同样的问题。
这就留下了当前的问题。鉴于 C++ 标准库的实现为标准库中的基本类型和类型定义了散列函数,那么将 std::hash 专门用于用户定义类型的简单而有效的方法是什么?有没有一种组合标准库实现提供的哈希函数的好方法?
(感谢 dyp 编辑。)StackOverflow 上的Another question 解决了如何组合散列函数的对。
其他 Google 搜索结果没有更多帮助。
ThisDobbs 博士的文章指出,两个令人满意的哈希值的异或将产生一个新的令人满意的哈希值。
This的文章似乎是从知识中说话,暗示了很多东西,但对细节很轻。它与 Dobbs 博士在第一个示例中的简短评论中的文章相矛盾,即使用 XOR 组合哈希函数会导致结果哈希函数较弱。
因为 XOR 应用于任何两个相等的值都会导致 0,我可以看到为什么 XOR 本身很弱。
元问题
一个合理的答案解释为什么这个问题是无效的并且一般不能回答也是受欢迎的。
【问题讨论】:
-
也许您应该将有关combining hashes 的问题添加到列表中?
-
嗯,我不确定。该答案适用于 两个 值,我不知道当递归应用于 N 个值时算法的质量是否足够好。似乎即使
tuple也不能使用标准设施进行哈希处理,请参阅stackoverflow.com/q/7110301 -
我们正在研究它的标准,但现在它很棘手。 open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3980.html 有一个很好的方法,但它使编译器更难优化。希望我们能够在接下来的 6 个月内解决这个问题(抱歉,标准很慢),并在下一个实验版本中加入一些东西。
-
这里有一个 open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3980.html 的公共域部分实现:github.com/HowardHinnant/hash_append/blob/master/hash_append.h 和大量使用它的示例代码:github.com/HowardHinnant/hash_append 你不能完全实现它,这就是为什么它必须进行标准化。但是,我现在在现实世界的项目中使用它已经足够好了。它消除了组合步骤,并允许您选择并轻松切换所使用的哈希算法,即使对于原始类型也是如此。
-
Bloomberg 刚刚开源了他们的生产质量 N3980 实施:github.com/bloomberg/bde/blob/master/groups/bsl/bslh/doc/…
标签: c++ c++11 unordered-map unordered-set hash-function