2012-08-03 89 views
5

Tôi phải sử dụng unordered_set cho một dự án khá lớn, và để đảm bảo rằng tôi đã sử dụng nó một cách chính xác, tôi đã thử một ví dụ nhỏ.Khai báo hàm băm cho unordered_set trong C++?

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

Khi tôi biên soạn tôi nhận được:

/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 

Nó có vẻ như nó không nhìn thấy hàm băm của tôi, nhưng tôi nghĩ "băm" là tên hàm mặc định. Tôi đã xác định hàm băm chính xác chưa? Hay tôi cần khai báo rõ ràng một lớp băm riêng biệt làm đối số mẫu thứ hai?

+1

Chức năng băm được truyền dưới dạng tham số mẫu phụ. Bạn cần (tốt hơn) một functor và làm 'unordered_set s (FooHasher());' – Xeo

Trả lời

8

Là một thay thế cho đề xuất của Xeo trong các nhận xét, bạn có thể cung cấp chuyên môn cho std::hash trước khi bạn tạo nhanh unordered_set.

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

Các foo tham số để phương pháp hash của bạn có vẻ không liên quan đến tôi, nhưng tôi thực hiện chuyên môn hóa vào giao diện mà bạn cung cấp.

+0

Ok cảm ơn, đã làm việc. Tôi thực sự đã không cho hàm băm của tôi để có một tham số thêm, đó là một lỗi đánh máy. Nó phải là size_t hash() const {return x;} Điều duy nhất tôi nhầm lẫn là tại sao tôi không thể chỉ tạo một hash() như tôi đã làm với toán tử ==()? Đối với nhà điều hành == tôi không phải làm gì thêm. – user1575106

+0

@ user1575106: Các API khác nhau sẽ có các yêu cầu khác nhau. Các nhà văn tiêu chuẩn không thể phục vụ cho mong muốn của mọi người, và giao diện đã cho làm cho nó dễ dàng để thử các thuật toán băm khác nhau mà không sửa đổi lớp. – jxh