如何组合 C++0x 中的哈希值?
C++0x 添加hash<...>(...)
。
不过,我找不到 hash_combine
函数,如 提升。实现这样的事情最干净的方法是什么?也许,使用 C++0x xor_combine
?
C++0x adds hash<...>(...)
.
I could not find a hash_combine
function though, as presented in boost. What is the cleanest way to implement something like this? Perhaps, using C++0x xor_combine
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
好吧,就像助推者那样做:
Well, just do it like the boost guys did it:
我将在这里分享它,因为它对于寻找此解决方案的其他人来说可能很有用:从 @KarlvonMoor 答案开始,这里有一个可变参数模板版本,如果您必须组合多个值,那么它的用法会更简洁一起:
用法:
这最初是为了实现可变参数宏而编写的,以便轻松地使自定义类型可哈希(我认为这是 hash_combine 函数的主要用法之一):
用法:
I'll share it here since it can be useful to others looking for this solution: starting from @KarlvonMoor answer, here's a variadic template version, which is terser in its usage if you have to combine several values together:
Usage:
This was written originally to implement a variadic macro to easily make custom types hashable (which I think is one of the primary usages of a
hash_combine
function):Usage:
我真的很喜欢 vt4a2h 的回答中的 C++17 方法,但是它遇到了一个问题:
Rest
通过值传递,而通过 const 引用传递它们会更可取(如果它可与仅移动类型一起使用,这是必须的)。这是改编后的版本,仍然使用 折叠表达式 (这就是为什么它需要 C++17 或更高版本)并使用
std::hash
(而不是 Qt 哈希函数):为了完整起见:此版本的
hash_combine 可用的所有类型
必须具有hash
模板专业化 > 注入到std
命名空间中。示例:
因此,上例中的类型
B
也可以在另一个类型A
中使用,如以下使用示例所示:I really like the C++17 approach from the answer by vt4a2h, however it suffers from a problem: The
Rest
is passed on by value whereas it would be more desirable to pass them on by const references (which is a must if it shall be usable with move-only types).Here is the adapted version which still uses a fold expression (which is the reason why it requires C++17 or above) and uses
std::hash
(instead of the Qt hash function):For completeness sake: All the types which shall be usable with this version of
hash_combine
must have a template specialization forhash
injected into thestd
namespace.Example:
So that type
B
in the example above is also usable within another typeA
, like the following usage example shows:几天前,我想出了稍微改进的版本这个答案(需要C++ 17支持):
上面的代码是在代码生成方面更好。我在代码中使用了 Qt 中的 qHash 函数,但也可以使用任何其他哈希器。
A few days ago I came up with slightly improved version of this answer (C++ 17 support is required):
The code above is better in terms of code generation. I used qHash function from Qt in my code, but it's also possible to use any other hashers.
vt4a2h 的 答案 当然很好,但使用 C++17 折叠表达式,并不是每个人都能够切换到更新的版本轻松使用工具链。下面的版本使用扩展器技巧来模拟折叠表达式,并且也适用于 C++11 和 C++14。
此外,我将函数标记为内联,并对可变参数模板参数使用完美转发。
编译器资源管理器上的实时示例
The answer by vt4a2h is certainly nice but uses the C++17 fold expression and not everyone is able to switch to a newer toolchain easily. The version below uses the expander trick to emulate a fold expression and works in C++11 and C++14 as well.
Additionally, I marked the function
inline
and use perfect forwarding for the variadic template arguments.Live example on Compiler Explorer
这也可以通过使用可变参数模板来解决,如下所示:
用法:
当然可以创建一个模板函数,但这可能会导致一些令人讨厌的类型推导,例如
hash("Hallo World!")
将计算一个指针上的哈希值而不是字符串上的哈希值。这可能就是标准使用结构的原因。This could also be solved by using a variadic template as follows:
Usage:
One could certainly make a template function, but this could cause some nasty type deduction e.g
hash("Hallo World!")
will calculate a hash value on the pointer rather than on the string. This is probably the reason, why the standard uses a struct.许多答案都基于
boost::hash_combine
。这是一个使用新的boost::hash_combine
混合函数的解决方案:我将其作为练习留给读者编写使用表达式折叠的可变参数模板版本。
Many of the answers are based on the old implementation of
boost::hash_combine
. Here's a solution that uses the newboost::hash_combine
mixing functions:I leave it as an exercise to the reader to write a variadic template version that uses expression folding.
Henri Menke的回答效果很好,但是如果您将警告视为错误,例如:
GCC 9.3.0将给出这个错误:
我们可以更新代码以避免这样的错误:
The answer by Henri Menke works great, but if you treat warnings as errors with for example:
GCC 9.3.0 will give this error:
We can update the code to avoid the error like this:
您可以使用 rst C++ 库我开发的目的是:
You can use the rst C++ library that I developed to do that: