2009-03-15 2 views
22

Как мне разрешить реализацию STL для моих пользовательских типов? На MSVC, есть класс std::tr1::hash, который я могу частично специализировать с помощьюКак расширить std :: tr1 :: hash для пользовательских типов?

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

, но это рекомендуемый способ? Кроме того, это работает и с реализацией GCC? Для boost::hash, этого достаточно, чтобы обеспечить бесплатную функцию size_t hash_value (const MyType&), есть ли что-то подобное для реализации TR1?

+0

Есть ли способ расширить std :: hash для пользовательских типов с частными конструкторами копирования? Кроме того, есть ли способ расширить его с помощью оператора(), который принимает константу ref вместо val? –

+0

В чем проблема со специализацией шаблона? Вы не берете копию своего объекта (вы передаете его по ссылкам), поэтому никаких проблем - и оператор() принимает const ref или значение, что бы вы ни хотели. Посмотрите на ответ Фила Нэша, который принимает объект как const ref. – Anteru

ответ

4

Да, это также будет работать для GCC. Я использую его в более крупном проекте, и он работает без проблем. Вы также можете предоставить свой собственный хэш-класс для контейнеров TR1, но указано, что std :: tr1 :: hash <> является стандартным хешированием класса. Специализация для пользовательских типов кажется естественным способом расширения стандартной хэш-функции.

3

Поскольку вы не добавляете в пространство имен библиотеки std, но предоставляете только специализации, тогда это нормально.

Если вы хотите предоставить более общий подход хэширования (например, хэш для кортежей в целом), посмотрите на Boost Fusion. Here is a simple example, который будет работать для большинства случаев (возможно, за исключением кортежей кортежей)

21

Я пытался выработать точный синтаксис для этого с неупорядоченными ассоциативными контейнерами (также используя GCC, поскольку OP был спрашивая) и ударил этот вопрос.

К сожалению, это не дошло до уровня детализации, который я хотел. Просматривая заголовки gcc о том, как они реализовали стандартные хеш-функции, я начал работать. Ввиду недостатка примеров (по крайней мере, на момент написания статьи) в Интернете, я думал, что это будет так же хорошо, как и любое место, чтобы опубликовать свой собственный пример (который я могу подтвердить, работает с 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 */; 
     } 
    }; 
}} 

(уведомление там являются два пространства имен здесь - это только мое соглашение для разрушения вложенных пространств имен)

0

следующий фрагмент кода показывает, как специализироваться std::tr1::unordered_map для отображения boost::const_string<char> к void* аналогично с тем, как std::string хешируется.

#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. 
Смежные вопросы