unordered_map/unordered_set 中元组的通用哈希
问:为什么 std::unordered_map
在标准 C 中,要使用元组作为关联容器(如 unordered_map 或 unordered_set)中的键,您需要定义自定义哈希函数。
问:可以在不使用可变参数模板的情况下对 C 0x 元组进行自动化吗?
可以,使用以下代码:
namespace std{ namespace { template <class T> inline void hash_combine(std::size_t& seed, T const& v) { seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); } template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1> struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { HashValueImpl<Tuple, Index-1>::apply(seed, tuple); hash_combine(seed, std::get<Index>(tuple)); } }; template <class Tuple> struct HashValueImpl<Tuple,0> { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get<0>(tuple)); } }; } template <typename ... TT> struct hash<std::tuple<TT...>> { size_t operator()(std::tuple<TT...> const& tt) const { size_t seed = 0; HashValueImpl<std::tuple<TT...> >::apply(seed, tt); return seed; } }; }
问:是否有更简单的解决方案?
标准不合格解决方案(启用 ADL):
#includenamespace std{ namespace { template <class T> inline void hash_combine(std::size_t& seed, T const& v) { seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); } template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1> struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { HashValueImpl<Tuple, Index-1>::apply(seed, tuple); hash_combine(seed, std::get<Index>(tuple)); } }; template <class Tuple> struct HashValueImpl<Tuple,0> { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get<0>(tuple)); } }; } template <typename ... TT> struct hash<std::tuple<TT...>> { size_t operator()(std::tuple<TT...> const& tt) const { size_t seed = 0; HashValueImpl<std::tuple<TT...> >::apply(seed, tt); return seed; } }; }
标准合格解决方案(无 ADL):
为了实现严格的标准一致性,您必须将上述代码移动到单独的命名空间(例如 hash_tuple)中,并修改语法以显式指定自定义哈希函数。
namespace hash_tuple{ // Forward non-tuple types to std::hash template <typename TT> struct hash { size_t operator()(TT const& tt) const { return std::hash<TT>()(tt); } }; }
替换 hash_combine 和来自不合格解决方案的 HashValueImpl 及其 hash_tuple 对应项。最后,使用以下语法:
unordered_set<tuple<double, int>, hash_tuple::hash<tuple<double, int>>> test2;
以上是如何在不定义自定义哈希函数的情况下使'std::unordered_map”工作?的详细内容。更多信息请关注PHP中文网其他相关文章!