2012-08-03 4 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

해시 기능은 추가 템플릿 매개 변수로 전달됩니다. Functor가 필요하고'unordered_set (FooHasher()); '가됩니다. – Xeo

답변

8

의견에서 Xeo의 제안에 대한 대안으로 을 인스턴스화하기 전에 std::hash의 전문 분야를 제공 할 수 있습니다.

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

당신의 hash 방법에 foo 매개 변수는 나에게 관계없는 것 같다,하지만 난 당신이 제공하는 인터페이스에 전문성을 구현했습니다.

+0

감사합니다. 실제로 해시 함수가 추가 매개 변수를 사용하지 않는 것은 오타입니다. size_t hash() const {return x;} 내가 혼동하는 유일한 이유는 왜 operator ==()와 같이 hash()를 만들 수 없습니까? 연산자 == 나는 여분의 일을 할 필요가 없었습니다. – user1575106

+0

@ user1575106 : API마다 요구 사항이 다릅니다. 표준 작성자는 모든 사람의 욕구를 충족시킬 수 없으며 주어진 인터페이스를 사용하면 클래스를 수정하지 않고도 다양한 해시 알고리즘을 쉽게 시도 할 수 있습니다. – jxh