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

时间:2015-02-06 14:26:02

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

我希望能够使用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<A, B>std::pair<B, A>)返回相同的种子。

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

问:

是否有标准方法来对std::pair进行哈希处理,以便忽略元素的顺序,并为std::pair<A, B>std::pair<B, A>返回相同的种子?

1 个答案:

答案 0 :(得分:10)

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

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]