2012-08-03 34 views
5

我必須使用unordered_set爲一個相當大的項目,並確保我正確使用它,我嘗試了一個小例子。在C++中聲明unordered_set的哈希函數?

#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; 
} 

我編譯時得到:

/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 

現在看來似乎不是看到我的哈希函數,但我認爲「哈希」是默認的函數名。我有沒有正確定義散列?或者我需要顯式聲明一個單獨的哈希類作爲第二個模板參數?

+1

散列函數作爲額外的模板參數傳遞。你需要(最好)一個函子,並做'unordered_set s(FooHasher());' – Xeo 2012-08-03 20:44:38

回答

8

作爲Xeo在評論中的建議的替代方案,您可以在實例化unordered_set之前爲std::hash提供專門化。

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

foo參數您hash方法似乎無關的給我,但我實現了專業化爲您提供的接口。

+0

好的謝謝,這工作。 我其實並沒有爲我的散列函數採取額外的參數,這是一個錯字。它應該是 size_t散列()const {return x;} 我唯一困惑的是爲什麼我不能像運算符==()那樣做一個散列()?對於運營商==我不必做任何額外的事情。 – user1575106 2012-08-03 22:07:00

+0

@ user1575106:不同的API會有不同的要求。標準編寫者不能滿足每個人的願望,並且給定的接口可以輕鬆地在不修改類的情況下嘗試不同的散列算法。 – jxh 2012-08-03 22:17:34