Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring hash function for unordered_set in c++? [duplicate]

I have to use unordered_set for a rather large project, and to make sure I was using it correctly I tried a small example.

#include <iostream>
#include <unordered_set>
using namespace std;

class Foo {
  private:
    int x;
  public:
    Foo(int in) {x = in;}
    bool operator==(const Foo& foo) const {return x == foo.x;}
    size_t hash(const Foo& foo) const {return x;}
};

int main() {
  Foo f1(3);
  unordered_set<Foo> s;
  s.insert(f1);
  return 0;
}

When I compile I get:

/tmp/cc3KFIf4.o: In function `std::__detail::_Hash_code_base<Foo, Foo, std::_Identity<Foo>, std::equal_to<Foo>, std::hash<Foo>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_hash_code(Foo const&) const':
hashset.cc:(.text._ZNKSt8__detail15_Hash_code_baseI3FooS1_St9_IdentityIS1_ESt8equal_toIS1_ESt4hashIS1_ENS_18_Mod_range_hashingENS_20_Default_ranged_hashELb0EE12_M_hash_codeERKS1_[std::__detail::_Hash_code_base<Foo, Foo, std::_Identity<Foo>, std::equal_to<Foo>, std::hash<Foo>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_hash_code(Foo const&) const]+0x19): undefined reference to `std::hash<Foo>::operator()(Foo) const'
/tmp/cc3KFIf4.o: In function `std::__detail::_Hash_code_base<Foo, Foo, std::_Identity<Foo>, std::equal_to<Foo>, std::hash<Foo>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_bucket_index(std::__detail::_Hash_node<Foo, false> const*, unsigned int) const':
hashset.cc:(.text._ZNKSt8__detail15_Hash_code_baseI3FooS1_St9_IdentityIS1_ESt8equal_toIS1_ESt4hashIS1_ENS_18_Mod_range_hashingENS_20_Default_ranged_hashELb0EE15_M_bucket_indexEPKNS_10_Hash_nodeIS1_Lb0EEEj[std::__detail::_Hash_code_base<Foo, Foo, std::_Identity<Foo>, std::equal_to<Foo>, std::hash<Foo>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_bucket_index(std::__detail::_Hash_node<Foo, false> const*, unsigned int) const]+0x28): undefined reference to `std::hash<Foo>::operator()(Foo) const'
collect2: ld returned 1 exit status

It seems like it's not seeing my hash function, but I thought "hash" was the default function name. Did I define hash correctly? Or do I need to explicitly declare a separate hash class as the second template argument?

like image 526
scottmsul Avatar asked Aug 03 '12 20:08

scottmsul


1 Answers

As an alternative to Xeo's suggestion in the comments, you can provide a specialization for std::hash before you instantiate the unordered_set.

namespace std {
    template <>
    struct hash<Foo> {
        size_t operator () (const Foo &f) const { return f.hash(f); }
    };
}

The foo parameter to your hash method seems extraneous to me, but I implemented the specialization to the interface you provided.

like image 181
jxh Avatar answered Nov 15 '22 10:11

jxh