使用unordered_set时,struct中嵌套结构的散列函数

Hashing function for nested struct in struct when using an unordered_set

本文关键字:嵌套 结构 散列函数 struct unordered set 使用      更新时间:2023-10-16

我试图使用一个unordered_set来维护一个唯一的结构体列表。我已经为结构体Name定义了散列函数,但是当我扩展Name结构体以包含另一个结构体成员Address时,我收到了编译错误。我知道我需要指定地址结构必须如何散列,但我似乎无法弄清楚在哪里/如何。

#include <unordered_set>
#include <string>
using namespace std;
struct Address
{
    int num;
};
struct Name
{
    string first;
    string second;
    Address address;
};

struct hashing_fn {
    size_t operator()(const Address &a ) const
    {
        return  hash<int>()(a.num);
    }
    size_t operator()(const Name &name ) const
    {
        return hash<string>()(name.first) ^ hash<string>()(name.second) ^ hash<Address>()(name.address);
    }
};
int main(int argc, char* argv[])
{
    unordered_set<Name,hashing_fn> ids;
    return 0;
}

更新

只是为了完成,这是修复:

template<>
struct hash<typename Address> {
    size_t operator()(const Address &a ) const
    {
        return  hash<int>()(a.num);
    }
};

您从未定义过hash<Address> !相反,您必须使用自己的函数operator()(name.address)


简单的XORing可能不是最好的解决方案。我强烈建议您复制Boost的hash_combine(),并将整个负载放入namespace std:

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 <> struct hash<Address>
  {
    inline size_t operator()(const Address & a) const
    {
      return hash<int>()(a.num);
    }
  };
  template <> struct hash<Name>
  {
    inline size_t operator()(const Name & a) const
    {
      size_t seed = 0;
      hash_combine(seed, name.first);
      hash_combine(seed, name.second);
      hash_combine(seed, name.address);
      return seed;
    }
  };
}

现在您可以直接使用这些类型(需要实现一个相等比较器):std::unordered_set<Name> s;