Нет ли специализаций std :: hash для стандартных контейнеров? - PullRequest
26 голосов
/ 06 ноября 2011

Я просто обнаружил, что немного удивлен тем, что не могу просто использовать

std::unordered_set<std::array<int, 16> > test;

потому что, кажется, нет std::hash специализации для std::array с. Это почему? Или я просто не нашел его? Если их действительно нет, можно ли упростить следующую попытку реализации?

namespace std
{
    template<typename T, size_t N>
    struct hash<array<T, N> >
    {
        typedef array<T, N> argument_type;
        typedef size_t result_type;

        result_type operator()(const argument_type& a) const
        {
            hash<T> hasher;
            result_type h = 0;
            for (result_type i = 0; i < N; ++i)
            {
                h = h * 31 + hasher(a[i]);
            }
            return h;
        }
    };
}

Я действительно чувствую, что это должно быть частью стандартной библиотеки.

Ответы [ 2 ]

12 голосов
/ 07 января 2012

Не ответ, а некоторая полезная информация.В февральском проекте стандарта C ++ 11 указано, что std::hash специализируется для следующих типов:

  • error_code § 19.5.5
  • bitset<N> § 20.5.3
  • unique_ptr<T, D> § 20.7.2.36
  • shared_ptr<T, D> § 20.7.2.36
  • type_index § 20.13.4
  • string § 21,6
  • u16string § 21,6
  • u32string § 21,6
  • wstring § 21,6
  • vector<bool, Allocator> § 23.3.8
  • thread::id § 30.3.1.1

И все эти типы: § 20.8.12

template <> struct hash<bool>;
template <> struct hash<char>;
template <> struct hash<signed char>;
template <> struct hash<unsigned char>;
template <> struct hash<char16_t>;
template <> struct hash<char32_t>;
template <> struct hash<wchar_t>;
template <> struct hash<short>;
template <> struct hash<unsigned short>;
template <> struct hash<int>;
template <> struct hash<unsigned int>;
template <> struct hash<long>;
template <> struct hash<long long>;
template <> struct hash<unsigned long>;
template <> struct hash<unsigned long long>;
template <> struct hash<float>;
template <> struct hash<double>;
template <> struct hash<long double>;
template<class T> struct hash<T*>;
11 голосов
/ 06 ноября 2011

Я не уверен, почему стандартная библиотека не включила это, но в Boost есть хэширование для всех видов вещей, созданных из типов, которые можно хэшировать. Ключевой функцией для этого является hash_combine, которую вы можете скопировать с boost/functional/hash/hash.hpp.

Используя hash_combine, Boost получает range_hash (просто объединяя хэши каждого элемента диапазона), а также хэши пар и кортежей. В свою очередь range_hash может использоваться для хеширования любого итерируемого контейнера.

...