如何std :: hash一个无序的std :: pair

101*_*010 7 c++ hash stl c++11 std-pair

我希望能够std::pair在unordered_container中使用a 作为键.我知道我可以通过以下方式执行此操作:

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;
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

但是,我希望散列忽略元素的顺序std::pair(即,为std::pair<A, B>和返回相同的种子)std::pair<B, A>).

我认为实现这一目标的一种方法是在创建我的时候应用某种排序std::pair<A, B>(即某种自定义std::make_pair).但由于对象A, B可能没有订单,因此限制性太强.

问:

是否有一种标准的方法来散列a std::pair,这样就忽略了元素的顺序,并且返回相同的种子std::pair<A, B>std::pair<B, A>

Rei*_*ica 14

不要订购配对,订购哈希:

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);
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

[实例]

  • 您也可以通过type_info :: before来订购它们,这可以消除一半的哈希计算(甚至可能是"if"检查,具体取决于优化器的优点). (4认同)