Как использовать unordered_set с пользовательскими типами? - PullRequest
14 голосов
/ 16 марта 2012

Требуется ли создание собственной хэш-функции для пользовательских типов?Нет ли значений по умолчанию, которые я могу использовать с unordered_set?

Ответы [ 2 ]

16 голосов
/ 16 марта 2012

Стандартная библиотека содержит специализации std::hash<T> для фундаментальных типов, для указателей и для std::string (точнее, для всех специализаций std::basic_string).

К сожалению, библиотека делает not содержит следующую жизненно важную функцию комбинирования новых из старых, которая, однако, является частью Boost и которую вы должны скопировать в свой код:

template <class T>
inline void hash_combine(std::size_t & seed, const T & v)
{
    std::hash<T> hasher;
    seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}

С помощью этой функции вы можете хэшировать пары,кортежи, массивы и диапазон элементов, которые сами по себе могут быть хэшируемыми.Просмотрите источники Boost для многих примеров и полезных реализаций.И, очевидно, вы можете использовать эту функцию для создания хеш-функции для ваших собственных типов.Например, вот хэширование пары:

template<typename S, typename T> struct pair_hash<std::pair<S, T>>
{
    inline std::size_t operator()(const std::pair<S, T> & v) const
    {
         std::size_t seed = 0;
         hash_combine(seed, v.first);
         hash_combine(seed, v.second);
         return seed;
    }
};

Имейте в виду, однако, что объединение хэшей не дает хороших хэш-значений.Результаты имеют очень плохие статистические качества (например, очень легко создавать коллизии хэшей).Хорошее хеширование должно быть в состоянии видеть все необработанные входные биты и не может быть учтено через частичные хеши.(Вот почему в текущей стандартной библиотеке нет лучшего решения; никто не смог придумать удовлетворительный дизайн.)

9 голосов
/ 16 марта 2012

Да, вам нужно написать собственную хеш-функцию. Это не так плохо, как кажется: если в вашем классе есть какой-либо хешируемый элемент, который, как вы знаете, будет достаточно уникальным, вы можете просто вернуть хеш этого члена.

Вы можете предоставить этот хэш, указав std::hash или явно передав класс хеша в качестве параметра шаблона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...