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