Нет ли специализаций std:: hash для стандартных контейнеров?
I только обнаружил, что я немного удивлен тем, что не могу просто использовать
std::unordered_set<std::array<int, 16> > test;
потому что для std::array
s не существует специализации std::hash
. Почему это? Или я просто не нашел его? Если их действительно нет, можно ли упростить следующую попытку реализации?
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;
}
};
}
Я действительно чувствую, что это должно как-то быть частью стандартной библиотеки.
Ответы
Ответ 1
Я не уверен, почему стандартная библиотека не включила это, но Boost имеет хеширование для всех видов вещей, состоящих из хешируемых типов. Ключевая функция для этого - hash_combine
, которую вы можете скопировать из boost/functional/hash/hash.hpp
.
Используя hash_combine
, Boost выводит range_hash
(просто комбинируя хэши каждого элемента диапазона), а также пары и кортежи. range_hash
в свою очередь может использоваться для хэширования любого итерабельного контейнера.
Ответ 2
Не ответ, а какая-то полезная информация. В февральском проекте стандарта С++ 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*>;