Hash function unordered_set

I am using std::unordered_set for the first time and asking a question about a hash function. As far as I understand, if you do not specify a hash function, std :: hash will be set by default.

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 an error message:

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

Do I need to define a transform function (to size_t) if you want to use unordered_set with a custom class? Is there a way to avoid writing my own hash function and just use the default value?

+7
source share
1 answer

If you do not specify your own hash functor as an argument to the template, the default is std::hash<MyClass> , which does not exist if you do not define it.

Better define your own specialization std::hash inside the 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 declaring your hash. That way, you can declare the hash simply as std::unordered_set<MyClass> without requiring further template arguments.

You did not specify what MyClass looks like inside, but the typical situation is that your custom type simply consists of several members of a simple type, for which there is a default hash function. In this case, you probably want to combine the hash values ​​for the individual types with the hash value for the whole combination. For this purpose, the Boost library provides a function called hash_combine . 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 probability of collisions), but this provides a good and convenient starting point.

Here's an example of how to use it, assuming MyClass is a two-line member:

 #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; } 
+12
source

All Articles