【问题标题】:How to std::hash an unordered std::pair如何对无序的 std::pair 进行 std::hash
【发布时间】:2015-04-06 17:19:24
【问题描述】:

我希望能够使用std::pair 作为 unordered_container 中的键。我知道我可以通过以下方式做到这一点:

template<typename T>
void
hash_combine(std::size_t &seed, T const &key) {
  std::hash<T> hasher;
  seed ^= hasher(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}

namespace std {
  template<typename T1, typename T2>
  struct hash<std::pair<T1, T2>> {
    std::size_t operator()(std::pair<T1, T2> const &p) const {
      std::size_t seed(0);
      ::hash_combine(seed, p.first);
      ::hash_combine(seed, p.second);
      return seed;
    }
  };
}

但是,我希望散列忽略 std::pair 中元素的顺序(即,为 std::pair&lt;A, B&gt;std::pair&lt;B, A&gt;) 返回相同的种子。

我认为实现此目的的一种方法是在创建我的std::pair&lt;A, B&gt; 时应用某种排序(即某种自定义std::make_pair)。 但这太严格了,因为对象 A, B 可能没有顺序。

问:

是否有一种标准方法来散列std::pair,从而忽略元素的顺序并为std::pair&lt;A, B&gt;std::pair&lt;B, A&gt; 返回相同的种子?

【问题讨论】:

  • 您可以使用^ 来组合哈希。另请参阅stackoverflow.com/questions/5889238/… 编辑:第二个想法:这可能对std::pair&lt;A, A&gt; 不利,因为所有具有相等值的对都将具有哈希0
  • @Wintermute 感谢您的回复,我已经看到了该线程,但是正如您已经提到的,由于您还提到了恶化,这不适合我的需求;)。跨度>
  • to return the same seed for std::pair&lt;A, B&gt; and std::pair&lt;B, A&gt; 为什么,如果你不介意我问?你想解决什么问题,这个(相当不寻常的)属性有什么帮助?
  • @Wintermute 这可以通过只采用单个模板参数的特化来解决,这与采用两个模板参数的特化不同。也许static_assert 以确保双参数模板的用户不会为两个模板参数提供相同的类型。不完美,但总比没有好。
  • 为什么不只是hash(first) + hash(second)

标签: c++ c++11 hash stl std-pair


【解决方案1】:

不要对对排序,对哈希排序:

namespace std {
  template<typename T1, typename T2>
  struct hash<std::pair<T1, T2>> {
    std::size_t operator()(std::pair<T1, T2> const &p) const {
      std::size_t seed1(0);
      ::hash_combine(seed1, p.first);
      ::hash_combine(seed1, p.second);

      std::size_t seed2(0);
      ::hash_combine(seed2, p.second);
      ::hash_combine(seed2, p.first);

      return std::min(seed1, seed2);
    }
  };
}

[Live example]

【讨论】:

  • 您也可以通过 type_info::before 对它们进行排序,这样可以消除一半的哈希计算(甚至可能还有“if”检查,具体取决于优化器的性能)。
  • @Nevin 你能提供一个活生生的例子吗?
  • 此解决方案不能从对扩展到任意长度的元组。
猜你喜欢
  • 2011-06-04
  • 1970-01-01
  • 2011-10-29
  • 2019-01-01
  • 2011-04-18
  • 2016-10-22
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
相关资源
最近更新 更多