Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inserting into an unordered_set with custom hash function

I have the following code to make an unordered_set<Interval>. This compiles fine.

struct Interval {   unsigned int begin;   unsigned int end;   bool updated;   //true if concat.  initially false   int patternIndex;  //pattern index. valid for single pattern   int proteinIndex;   //protein index.  for retrieving the pattern };  struct Hash {   size_t operator()(const Interval &interval); };  size_t Hash::operator()(const Interval &interval){   string temp = to_string(interval.begin) + to_string(interval.end) + to_string(interval.proteinIndex);   return hash<string>()(temp); }  unordered_set<Interval, string, Hash> test; 

However, I cannot compile when I try to insert using this code:

for(list<Interval>::iterator i = concat.begin(); i != concat.end(); ++i){   test.insert((*i)); } 

Moreover, I cannot determine what the problem is from the error messages, for example:

note: candidate is: note: size_t Hash::operator()(const Interval&) note:   candidate expects 1 argument, 2 provided   

I thought I only provided 1 argument...

What is the problem with my insertion code?


Here's the new instantiation code: unordered_set<Interval, Hash> test; However, I'm still receiving a slew of error messages, for example:

note: candidate is: note: size_t Hash::operator()(const Interval&) <near match> note:   no known conversion for implicit ‘this’ parameter from ‘const Hash*’ to ‘Hash*’ 
like image 440
user2052561 Avatar asked Apr 07 '13 23:04

user2052561


People also ask

Is unordered_set a hash table?

An unordered_set is implemented using a hash table where keys are hashed into indices of a hash table so that the insertion is always randomized.

Can we insert pair in unordered_set C++?

An unordered set of pairs is an unordered set in which each element is a pair itself. By default, C++ doesn't allow us to create an unordered set of pairs directly but one can pass a hash function to the unordered set container.

Which hash function is used in Unordered_map?

The unordered_map::hash_function() is a built in function in C++ STL which is used to get the hash function. This hash function is a unary function which takes a single argument only and returns a unique value of type size_t based on it.

Can we use pair in unordered_set?

We can use it to hash integers, floats, pointers, strings, arrays, pairs, and standard containers. That's all about using pair as a key in std::unordered_set in C++.


1 Answers

First problem:

You are passing string as the second template argument for your instantiation of the unordered_set<> class template. The second argument should be the type of your hasher functor, and std::string is not a callable object.

Perhaps meant to write:

unordered_set<Interval, /* string */ Hash> test; //                      ^^^^^^^^^^^^ //                      Why this? 

Also, I would suggest using names other than begin and end for your (member) variables, since those are names of algorithms of the C++ Standard Library.

Second problem:

You should keep in mind, that the hasher function should be qualified as const, so your functor should be:

struct Hash {    size_t operator() (const Interval &interval) const {    //                                           ^^^^^    //                                           Don't forget this!      string temp = to_string(interval.b) +                     to_string(interval.e) +                     to_string(interval.proteinIndex);      return (temp.length());    } }; 

Third problem:

Finally, if you want std::unordered_set to be able to work with objects of type Interval, you need to define an equality operator consistent with your hash function. By default, if you do not specify any type argument as the third parameter of the std::unordered_set class template, operator == will be used.

You currently do not have any overload of operator == for your class Interval, so you should provide one. For example:

inline bool operator == (Interval const& lhs, Interval const& rhs) {     return (lhs.b == rhs.b) &&             (lhs.e == rhs.e) &&             (lhs.proteinIndex == rhs.proteinIndex);  } 

Conclusion:

After all the above modifications, you can see your code compiling in this live example.

like image 190
Andy Prowl Avatar answered Sep 19 '22 11:09

Andy Prowl