Как расширить std:: tr1:: hash для пользовательских типов?
Как мне разрешить реализацию STL для моих пользовательских типов? В MSVC существует класс std::tr1::hash
, который я могу частично специализировать с помощью
namespace std
{
namespace tr1
{
template <>
struct hash<MyType>
{ ... };
}
}
но это рекомендуемый способ? Кроме того, работает ли это с реализацией GCC? Для boost::hash
достаточно предоставить свободную функцию size_t hash_value (const MyType&)
, есть ли что-то подобное для реализации TR1?
Ответы
Ответ 1
Да, это также будет работать для GCC. Я использую его в более крупном проекте, и он работает без проблем. Вы также можете предоставить собственный собственный хэш-класс для контейнеров TR1, но указано, что std:: tr1:: hash < > является классом хэширования по умолчанию. Специализация для пользовательских типов кажется естественным способом расширения стандартной хэш-функции.
Ответ 2
Я пытался выработать точный синтаксис для этого с неупорядоченными ассоциативными контейнерами (также используя 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 */;
}
};
}}
(обратите внимание, что здесь есть два пространства имён - это только мое соглашение о сворачивании вложенных пространств имен)
Ответ 3
Поскольку вы не добавляете в пространство имен библиотеки std
, но только предоставляете специализации, тогда это нормально.
Если вы хотите предоставить более общий подход хэширования (например, хэш для кортежей в целом), посмотрите на Boost Fusion. Вот простой пример, который будет работать для большинства случаев (вероятно, с исключением для кортежей кортежей)
Ответ 4
В следующем фрагменте кода показано, как специализировать 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.