Inserting into an unordered_set with custom hash function

c++, c++11, unordered-set

Solution

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, your code becomes:

#include <string>
#include <unordered_set>
#include <list>

using namespace std;

struct Interval {
  unsigned int b;
  unsigned int e;
  bool updated;   //true if concat.  initially false
  int patternIndex;  //pattern index. valid for single pattern
  int proteinIndex;   //protein index.  for retrieving the pattern
};

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

struct Hash {
   size_t operator()(const Interval &interval) const {
     string temp = to_string(interval.b) + to_string(interval.e) + to_string(interval.proteinIndex);
     return (temp.length());
   }
};

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

}

Problem

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*’ ```

Original source

Related problems