2009-03-15 26 views
22

Làm cách nào để cho phép triển khai STL nhận các loại tùy chỉnh của tôi? Trên MSVC, có một lớp học std::tr1::hash, mà tôi có thể chuyên về một phần bằng cách sử dụngLàm cách nào để mở rộng std :: tr1 :: hash cho các loại tùy chỉnh?

namespace std 
{ 
    namespace tr1 
    { 
     template <> 
     struct hash<MyType> 
     { ... }; 
    } 
} 

nhưng đây có phải là cách được khuyến nghị không? Hơn nữa, điều này có làm việc với việc thực hiện GCC không? Đối với boost::hash, đủ để cung cấp chức năng miễn phí size_t hash_value (const MyType&), có điều gì tương tự cho việc triển khai TR1 không?

+0

Có cách nào để mở rộng std :: hash cho các loại do người dùng xác định với các nhà xây dựng bản sao riêng không? Ngoài ra, là có một cách để mở rộng nó với một nhà điều hành() mà mất một const ref thay vì val? –

+0

Sự cố với chuyên môn mẫu là gì? Bạn không lấy một bản sao của đối tượng của bạn (bạn vượt qua nó bằng tài liệu tham khảo), do đó, không có vấn đề - và các nhà điều hành() mất một const ref hoặc giá trị, bất cứ điều gì bạn muốn. Nhìn vào câu trả lời của Phil Nash, lấy đối tượng là const ref. – Anteru

Trả lời

4

Có, điều này cũng sẽ hoạt động đối với GCC. Tôi đang sử dụng nó trong một dự án lớn hơn và nó hoạt động mà không có vấn đề gì. Bạn cũng có thể cung cấp lớp băm tùy chỉnh của riêng bạn cho các thùng chứa TR1, nhưng nó được xác định rằng std :: tr1 :: hash <> là lớp băm mặc định. Chuyên môn cho các loại tùy chỉnh có vẻ giống như cách tự nhiên để mở rộng chức năng băm tiêu chuẩn.

3

Vì bạn không thêm vào không gian tên thư viện std, nhưng chỉ cung cấp các chuyên môn, sau đó nó hoàn toàn OK.

Nếu bạn muốn cung cấp cách tiếp cận băm chung hơn (ví dụ: băm cho các bộ dữ liệu nói chung) thì hãy xem Boost Fusion. Here is a simple example, sẽ hoạt động cho hầu hết các trường hợp (có thể có ngoại lệ cho bộ tuple)

21

Tôi đã cố gắng tìm ra cú pháp chính xác để thực hiện điều này với các thùng chứa liên kết không sắp xếp (cũng sử dụng GCC, vì OP hỏi) và nhấn câu hỏi này.

Rất tiếc, nó không giảm xuống mức chi tiết mà tôi muốn. Bằng cách xem qua các tiêu đề gcc về cách chúng đã triển khai các hàm băm tiêu chuẩn mà tôi đã làm việc. Theo quan điểm của các ví dụ (ít nhất là tại thời điểm viết) trên web, tôi nghĩ đây sẽ là nơi tốt để đăng ví dụ của tôi (mà tôi có thể xác nhận với GCC):


namespace std { namespace tr1 
{ 
    template <> 
    struct hash<MyType> : public unary_function<MyType, size_t> 
    { 
     size_t operator()(const MyType& v) const 
     { 
      return /* my hash algorithm */; 
     } 
    }; 
}} 

(thông báo có hai không gian tên ở đây - đó chỉ là ước của tôi cho sụp đổ namespace lồng nhau)

0

đoạn mã sau đây cho thấy làm thế nào để chuyên std::tr1::unordered_map để lập bản đồ boost::const_string<char> để void* Tương tự với cách std::string được băm.

#include <boost/const_string/const_string.hpp>  
typedef class boost::const_string<char> csc; 

namespace std 
{ 
namespace tr1 
{ 
template <> 
struct hash<csc> { 
public: 
    size_t operator()(const csc & x) const { 
     return std::_Hash_impl::hash(x.data(), x.size()); 
    } 
}; 
} 
} 

typedef std::tr1::unordered_map<csc, void*> Map; 
typedef Map::value_type Dual; ///< Element Type. 
Các vấn đề liên quan