自定义类的unordered_set是否有默认的哈希函数? [英] Is there a default hash function for an unordered_set of a custom class?

查看:187
本文介绍了自定义类的unordered_set是否有默认的哈希函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我第一次使用std::unordered_set,并且对哈希函数有疑问.据我了解,如果您不指定哈希函数,它将默认为std::hash<Key>.

我在一个班上有一个mySet成员:

typedef std::unordered_set<MyClass> USetType;
USetType mySet;

当我尝试构建时,出现以下错误:

错误C2440:类型转换":无法从"const MyClass"转换为"size_t"

如果要将unordered_set与自定义类一起使用,是否有必要定义转换函数(到size_t)?有什么方法可以避免编写自己的哈希函数,而只使用默认值?

解决方案

如果您未将自己的哈希函子指定为模板参数,则默认为std::hash<MyClass>,除非您定义它,否则将不存在. >

最好在名称空间std中定义自己对std::hash的专业化:

namespace std {
  template <>
  struct hash<MyClass>
  {
    typedef MyClass      argument_type;
    typedef std::size_t  result_type;

    result_type operator()(const MyClass & t) const
    {
       /* ..calculate hash value for t */
    }
  };
}

并确保在哈希声明之前 包含此代码.这样,您可以将哈希简单声明为std::unordered_set<MyClass>,而无需其他模板参数.

您没有指定MyClass的内部外观,但是典型的情况是您的用户定义类型仅由几个简单类型成员组成,而这些成员具有默认的哈希函数.在这种情况下,您可能希望将单个类型的哈希值组合为整个组合的哈希值.为此,Boost库提供了一个名为hash_combine的函数.当然,不能保证它在您的特定情况下会很好地工作(这取决于数据值的分布和冲突的可能性),但是它提供了一个很好且易于使用的起点.

这里是使用它的示例,假设MyClass由两个字符串成员组成:

#include <unordered_set>
#include <boost/functional/hash.hpp>

struct MyClass
{
  std::string _s1;
  std::string _s2;
};

namespace std {
  template <>
  struct hash<MyClass>
  {
    typedef MyClass      argument_type;
    typedef std::size_t  result_type;

    result_type operator()(const MyClass & t) const
    {
      std::size_t val { 0 };
      boost::hash_combine(val,t._s1);
      boost::hash_combine(val,t._s2);
      return val;
    }
  };
}

int main()
{
  std::unordered_set<MyClass> s;
  /* ... */
  return 0;
}

I'm using a std::unordered_set for the first time and have a question about the hash function. As far as I understand, if you don't specify a hash function it will default to std::hash<Key>.

I have a mySet member in one of my classes:

typedef std::unordered_set<MyClass> USetType;
USetType mySet;

When I try to build, I get the following error:

error C2440: 'type cast' : cannot convert from 'const MyClass' to 'size_t'

Is it necessary to define a conversion function (to size_t) if you want to use unordered_set with a custom class? Is there any way to avoid writing your own hash function and just using the default?

解决方案

If you don't specify your own hash functor as template argument, it will default to std::hash<MyClass>, which does not exist unless you define it.

Best define your own specialization of std::hash inside namespace std:

namespace std {
  template <>
  struct hash<MyClass>
  {
    typedef MyClass      argument_type;
    typedef std::size_t  result_type;

    result_type operator()(const MyClass & t) const
    {
       /* ..calculate hash value for t */
    }
  };
}

And make sure you include this code before the declaration of your hash. This way you can declare the hash simply as std::unordered_set<MyClass> with no need for further template arguments.

You didn't specify what MyClass looks like inside, but a typical situation is that your user-defined type simply consists of several simple-type members, for which a default hash function exists. In this case, you will probably want to combine the hash values for the individual types to a hash value for the entire combination. The Boost library provides a function called hash_combine for this purpose. Of course, there is no guarantee that it will work well in your particular case (it depends on the distribution of data values and the likelihood of collisions), but it provides a good and easy-to-use starting point.

Here is an example of how to use it, assuming MyClass consists of two string members:

#include <unordered_set>
#include <boost/functional/hash.hpp>

struct MyClass
{
  std::string _s1;
  std::string _s2;
};

namespace std {
  template <>
  struct hash<MyClass>
  {
    typedef MyClass      argument_type;
    typedef std::size_t  result_type;

    result_type operator()(const MyClass & t) const
    {
      std::size_t val { 0 };
      boost::hash_combine(val,t._s1);
      boost::hash_combine(val,t._s2);
      return val;
    }
  };
}

int main()
{
  std::unordered_set<MyClass> s;
  /* ... */
  return 0;
}

这篇关于自定义类的unordered_set是否有默认的哈希函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆