std::hash
Определено в заголовке <functional> | ||
|---|---|---|
template< class Key > struct hash; | (с C++11) |
Каждая специализация этого шаблона либо включена ("незатронута"), либо выключена ("отравлена").
Включённые специализации шаблона hash определяют объект-функцию, реализующую функцию хеширования. Экземпляры этого объекта-функции удовлетворяют требованию Hash. В частности, они определяют operator() const, который:
- Принимает единственный параметр типа
Key. - Возвращает значение типа
std::size_t, которое представляет собой значение хеша параметра. - Не выбрасывает исключения при вызове.
- Для двух параметров
k1иk2, которые равны,std::hash<Key>()(k1) == std::hash<Key>()(k2). - Для двух различных параметров
k1иk2, которые не равны, вероятность того, чтоstd::hash<Key>()(k1) == std::hash<Key>()(k2)должна быть очень мала, приближаясь к1.0 / std::numeric_limits<std::size_t>::max().
Все явные и частичные специализации std::hash, предоставляемые стандартной библиотекой, являются DefaultConstructible, CopyAssignable, Swappable и Destructible. Специализации hash, предоставленные пользователем, также должны соответствовать этим требованиям.
Неупорядоченные ассоциативные контейнеры std::unordered_set, std::unordered_multiset, std::unordered_map, std::unordered_multimap используют специализации шаблона std::hash в качестве функции хеширования по умолчанию.
Для каждого типа Key, для которого ни библиотека, ни пользователь не предоставляет включённую специализацию std::hash<Key>, эта специализация существует и отключена. Отключенные специализации не удовлетворяют требованию Hash, не удовлетворяют требованию FunctionObject, и следующие значения являются всеми false:
-
std::is_default_constructible<std::hash<Key>>::value -
std::is_copy_constructible<std::hash<Key>>::value -
std::is_move_constructible<std::hash<Key>>::value -
std::is_copy_assignable<std::hash<Key>>::value -
std::is_move_assignable<std::hash<Key>>::value
Другими словами, они существуют, но не могут быть использованы.
Примечания
Фактические функции хеширования зависят от реализации и не обязаны удовлетворять никаким другим критериям качества, кроме указанных выше. Обратите внимание, что некоторые реализации используют тривиальные (тождественные) функции хеширования, которые отображают целое число на себя. Другими словами, эти функции хеширования предназначены для работы с неупорядоченными ассоциативными контейнерами, но не как криптографические хеши, например.
Функции хеширования обязаны производить одинаковый результат для одинакового входного значения в рамках одного выполнения программы; это позволяет использовать солёные хеши, что предотвращает атаки на отказ в обслуживании, связанные с коллизиями.
Нет специализации для строк C. std::hash<const char*> производит хеш значения указателя (адрес памяти), она не анализирует содержимое массива символов.
Типы членов
| (до C++20) |
Члены-функции
| создаёт объект функции хеширования (публичная функция-член) |
|
| вычисляет хеш аргумента (публичная функция-член) |
Стандартные специализации для основных типов
Определено в заголовке <functional> | ||
|---|---|---|
template<> struct hash<bool>; template<> struct hash<char>; template<> struct hash<signed char>; template<> struct hash<unsigned char>; template<> struct hash<char8_t>; // C++20 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<> struct hash<std::nullptr_t>; template< class T > struct hash<T*>; |
Помимо вышеперечисленного, стандартная библиотека предоставляет специализации для всех (скопированных и нескопированных) типов перечислений. Они могут быть (но не обязаны быть) реализованы как std::hash<std::underlying_type<Enum>::type>.
Стандартная библиотека предоставляет включенные специализации std::hash для std::nullptr_t и всех cv-неквалифицированных арифметических типов (включая любые расширенные целочисленные типы), всех типов перечислений и всех типов указателей.
Каждый заголовок стандартной библиотеки, который объявляет шаблон std::hash , предоставляет все включенные специализации, описанные выше:
| (с C++17) | |
| (с C++20) | |
| (с C++23) | |
| (с C++26) |
| Все функции-члены всех специализаций стандартной библиотеки этого шаблона являются noexcept, за исключением функций-членов:
| (с C++17) |
Стандартные специализации для типов библиотеки
|
(C++20) | Поддержка хеширования для std::coroutine_handle (специализация шаблона класса) |
|
(C++11) | Поддержка хеширования для std::error_code (специализация шаблона класса) |
|
(C++17) | Поддержка хеширования для std::error_condition (специализация шаблона класса) |
|
(C++23) | Поддержка хеширования для std::stacktrace_entry (специализация шаблона класса) |
|
(C++23) | Поддержка хеширования для std::basic_stacktrace (специализация шаблона класса) |
|
(C++17) | Поддержка хеширования для std::optional (специализация шаблона класса) |
|
(C++17) | Поддержка хеширования для std::variant (специализация шаблона класса) |
|
(C++17) | Поддержка хеширования для std::monostate (специализация шаблона класса) |
|
(C++11) | Поддержка хеширования для std::bitset (специализация шаблона класса) |
|
(C++11) | Поддержка хеширования для std::unique_ptr (специализация шаблона класса) |
|
(C++11) | Поддержка хеширования для std::shared_ptr (специализация шаблона класса) |
|
(C++11) | Поддержка хеширования для std::type_index (специализация шаблона класса) |
|
(C++11) | Поддержка хеширования для строк (специализация шаблона класса) |
|
(C++17)(C++17)(C++20)(C++17)(C++17) | Поддержка хеширования для представлений строк (специализация шаблона класса) |
|
(C++11) | Поддержка хеширования для std::vector<bool> (специализация шаблона класса) |
|
(C++17) | Поддержка хеширования для std::filesystem::path (специализация шаблона класса) |
|
(C++11) | Поддержка хеширования для std::thread::id (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::duration (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::time_point (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::day (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::month (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::year (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::weekday (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::weekday_indexed (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::weekday_last (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::month_day (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::month_day_last (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::month_weekday (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::month_weekday_last (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::year_month (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::year_month_day (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::year_month_day_last (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::year_month_weekday (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::year_month_weekday_last (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::zoned_time (специализация шаблона класса) |
|
(C++26) | Поддержка хеширования для std::chrono::leap_second (специализация шаблона класса) |
Примечание: дополнительные специализации для std::pair и стандартных типов контейнеров, а также служебные функции для составления хешей доступны в boost::hash.
Пример
#include <cstddef>
#include <functional>
#include <iomanip>
#include <iostream>
#include <string>
#include <unordered_set>
struct S
{
std::string first_name;
std::string last_name;
bool operator==(const S&) const = default; // since C++20
};
// Before C++20.
// bool operator==(const S& lhs, const S& rhs)
// {
// return lhs.first_name == rhs.first_name && lhs.last_name == rhs.last_name;
// }
// Custom hash can be a standalone function object.
struct MyHash
{
std::size_t operator()(const S& s) const noexcept
{
std::size_t h1 = std::hash<std::string>{}(s.first_name);
std::size_t h2 = std::hash<std::string>{}(s.last_name);
return h1 ^ (h2 << 1); // or use boost::hash_combine
}
};
// Custom specialization of std::hash can be injected in namespace std.
template<>
struct std::hash<S>
{
std::size_t operator()(const S& s) const noexcept
{
std::size_t h1 = std::hash<std::string>{}(s.first_name);
std::size_t h2 = std::hash<std::string>{}(s.last_name);
return h1 ^ (h2 << 1); // or use boost::hash_combine
}
};
int main()
{
std::string str = "Meet the new boss...";
std::size_t str_hash = std::hash<std::string>{}(str);
std::cout << "hash(" << std::quoted(str) << ") =\t" << str_hash << '\n';
S obj = {"Hubert", "Farnsworth"};
// Using the standalone function object.
std::cout << "hash(" << std::quoted(obj.first_name) << ", "
<< std::quoted(obj.last_name) << ") =\t"
<< MyHash{}(obj) << " (using MyHash) or\n\t\t\t\t"
<< std::hash<S>{}(obj) << " (using injected specialization)\n";
// Custom hash makes it possible to use custom types in unordered containers.
// The example will use the injected std::hash<S> specialization above,
// to use MyHash instead, pass it as a second template argument.
std::unordered_set<S> names = {obj, {"Bender", "Rodriguez"}, {"Turanga", "Leela"}};
for (auto const& s: names)
std::cout << std::quoted(s.first_name) << ' '
<< std::quoted(s.last_name) << '\n';
}Возможный вывод:
hash("Meet the new boss...") = 10656026664466977650
hash("Hubert", "Farnsworth") = 12922914235676820612 (using MyHash) or
12922914235676820612 (using injected specialization)
"Bender" "Rodriguez"
"Turanga" "Leela"
"Hubert" "Farnsworth"Отчеты об ошибках
Следующие отчеты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применено к | Поведение, как опубликовано | Правильное поведение |
|---|---|---|---|
| LWG 2148 | C++11 | специализации для перечислений отсутствовали | предоставлены |
| LWG 2543 | C++11 |
std::hash могла быть несовместима со SFINAE | сделана совместимой со SFINAE с помощью отключенных специализаций |
| LWG 2817 | C++11 | специализация для std::nullptr_t отсутствовала | предоставлена |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/utility/hash