std :: unordered_set中hasher和key_equal之间的关系

时间:2014-08-28 19:36:36

标签: c++ hash unordered-set

我想说,hasherkey_equal之间必然存在关系。如果两个元素相同(调用equal返回true),则它们必须具有相同的散列,否则将搜索错误的存储区元素。

但在http://www.cplusplus.com/reference/unordered_set/unordered_set/http://en.cppreference.com/w/cpp/container/unordered_set

上没有写过这样的内容

但它显然无法正常工作。 参见示例,当我尝试独立于元素的顺序(1,2 == 2,1)

过滤对
#include <iostream>
#include <functional>
#include <unordered_set>

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

namespace std
{
  template<typename S, typename T>
  struct hash<pair<S, T>>
  {
    inline size_t operator()(const pair<S, T> & v) const
    {
      size_t seed = 0;
      ::hash_combine(seed, v.first);
      ::hash_combine(seed, v.second);
      return seed;
    }
  };
}

int main() 
{
   typedef std::pair<int, int> Pair;
    Pair pa = std::make_pair(7,5);
    Pair pb = std::make_pair(5,7);
    Pair pc = std::make_pair(5,1);
    Pair pd = std::make_pair(4,3);
    Pair pe = std::make_pair(5,7);

    struct PairEq
    {
        inline bool operator()(const Pair & p1, const Pair & p2) const
        {
            return (p1.first == p2.first && p1.second == p2.second)
                || (p1.first == p2.second && p1.second == p2.first);
        }
    };

    std::unordered_set<Pair, std::hash<Pair>> h;

    h.insert(pa);
    h.insert(pb);
    h.insert(pc);
    h.insert(pd);
    h.insert(pe);

   for(auto & p : h)
   {
      std::cout << p.first << " " << p.second << "\n";
   }

   // note 5,7 AND 7,5 is outputted
}

假设通常的哈希属性是否安全 :如果两个元素相等,则它们具有相同的散列。两个相同的哈希值并不代表相同的元素?

1 个答案:

答案 0 :(得分:4)

是的,这个关系是必需的,按照C ++标准,第23.2.5 / 5节[unord.req] - (无序关联容器,强调我的)

  

容器的Hash类型的对象 - 由hash表示 - 称为散列函数   容器。容器的Pred类型的对象 - 由pred表示 - 称为   容器的关键等式谓词。

     

如果容器的键等式谓词在传递这些值时返回true,则认为Key类型的两个值k1和k2是等效的。 如果k1和k2是等价的,则容器的散列函数应为返回相同的值。


请注意,此要求代表所有无序关联容器,而不仅仅是std::unordered_set