std::hash
Определён в заголовочном файле <bitset> | ||
|---|---|---|
Определён в заголовочном файле <coroutine> | ||
Определён в заголовочном файле <chrono> | (начиная с C++26) | |
Определён в заголовочном файле <filesystem> | ||
Определён в заголовочном файле <functional> | ||
Определён в заголовочном файле <memory> | ||
Определён в заголовочном файле <optional> | ||
Определён в заголовочном файле <stacktrace> | ||
Определён в заголовочном файле <string> | ||
Определён в заголовочном файле <string_view> | ||
Определён в заголовочном файле <system_error> | ||
Определён в заголовочном файле <text_encoding> | ||
Определён в заголовочном файле <thread> | ||
Определён в заголовочном файле <typeindex> | ||
Определён в заголовочном файле <variant> | ||
Определён в заголовочном файле <vector> | ||
template< class Key > struct hash; | (начиная с C++11) |
Неупорядоченные ассоциативные контейнеры std::unordered_set, std::unordered_multiset, std::unordered_map, std::unordered_multimap используют специализации шаблона std::hash в качестве хеш-функции по умолчанию.
Для типа Key каждая специализация std::hash<Key> либо включена, либо отключена :
- Если программа или пользователь не предоставляет
std::hash<Key>, она отключена. - В противном случае
std::hash<Key>включена, если выполнены все следующие условия: - Выполнены все следующие требования:
-
Hash (с
Keyв качестве типа аргумента вызова функции) - DefaultConstructible
- CopyAssignable
- Swappable
- При следующих значениях:
-
h, объект типаstd::hash<Key>. -
k1иk2, объекты типаKey.
-
- Выполнены все следующие требования:
- Если
k1 == k2равноtrue, тоh(k1) == h(k2)также равноtrue. - Если
std::hash<Key>не является специализацией, определённой программой,h(k1)никогда не генерирует исключение.
- Если
- В противном случае
std::hash<Key>отключена.
Отключённые специализации не удовлетворяют требованиям Hash и FunctionObject, а все следующие значения равны false:
std::is_default_constructible<std::hash<Key>>::valuestd::is_copy_constructible<std::hash<Key>>::valuestd::is_move_constructible<std::hash<Key>>::valuestd::is_copy_assignable<std::hash<Key>>::valuestd::is_move_assignable<std::hash<Key>>::value
Иными словами, они существуют, но их нельзя использовать.
Вложенные типы
| (до C++20) |
Функции-члены
| создаёт объект хеш-функции (открытая функция-член) |
|
| вычисляет хеш аргумента (открытая функция-член) |
Специализации стандартной библиотеки
Каждый заголовочный файл, объявляющий шаблон std::hash, также предоставляет включённые специализации std::hash для следующих типов:
- все арифметические типы без cv-квалификаторов
- все типы перечислений без cv-квалификаторов
- все типы указателей без cv-квалификаторов
std::nullptr_t
Кроме того, некоторые заголовочные файлы предоставляют другие включённые специализации std::hash для библиотечных типов (см. ниже).
| Для всех специализаций
| (начиная с C++17) |
Специализации для библиотечных типов
Библиотека поддержки языка |
|
|
(C++20) | поддержка хеширования для std::coroutine_handle (специализация шаблона класса) |
Библиотека диагностики |
|
|
(C++11) | поддержка хеширования для std::error_code (специализация шаблона класса) |
|
(C++17) | поддержка хеширования для std::error_condition (специализация шаблона класса) |
|
(C++11) | поддержка хеширования для std::type_index (специализация шаблона класса) |
|
(C++23) | поддержка хеширования для std::stacktrace_entry (специализация шаблона класса) |
|
(C++23) | поддержка хеширования для std::basic_stacktrace (специализация шаблона класса) |
Библиотека управления памятью |
|
|
(C++11) | поддержка хеширования для std::unique_ptr (специализация шаблона класса) |
|
(C++11) | поддержка хеширования для std::shared_ptr (специализация шаблона класса) |
|
(C++26) | поддержка хеширования для std::indirect (специализация шаблона класса) |
Библиотека общих утилит |
|
|
(C++17) | поддержка хеширования для std::optional (специализация шаблона класса) |
|
(C++17) | поддержка хеширования для std::variant (специализация шаблона класса) |
|
(C++17) | поддержка хеширования для std::monostate (специализация шаблона класса) |
|
(C++11) | поддержка хеширования для std::bitset (специализация шаблона класса) |
Библиотека контейнеров |
|
|
(C++11) | поддержка хеширования для std::vector<bool> (специализация шаблона класса) |
Библиотека строк |
|
|
(C++11) | поддержка хеширования для строк (специализация шаблона класса) |
|
(C++17)(C++17)(C++20)(C++17)(C++17) | поддержка хеширования для представлений строк (специализация шаблона класса) |
Библиотека обработки текста |
|
|
(C++26) | поддержка хеширования для std::text_encoding (специализация шаблона класса) |
Библиотека измерения времени |
|
|
(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 (специализация шаблона класса) |
Библиотека ввода-вывода |
|
|
(C++17) | поддержка хеширования для std::filesystem::path (специализация шаблона класса) |
Библиотека поддержки параллелизма |
|
|
(C++11) | поддержка хеширования для std::thread::id (специализация шаблона класса) |
Примечания
Конкретные хеш-функции зависят от реализации; от них не требуется соответствовать каким-либо другим критериям качества, кроме указанных выше. В частности, некоторые реализации используют тривиальные (тождественные) хеш-функции, которые сопоставляют целому числу его же значение. Иными словами, эти хеш-функции предназначены для работы с неупорядоченными ассоциативными контейнерами, но не, например, в качестве криптографических хеш-функций.
Хеш-функции должны выдавать одинаковый результат для одинакового входного значения только в пределах одного выполнения программы; это позволяет использовать хеши с солью, предотвращающие атаки типа «отказ в обслуживании» посредством коллизий.
Специализации для строк C отсутствуют. std::hash<constchar*> вычисляет хеш значения указателя (адреса в памяти), не проверяя содержимое массива символов.
Дополнительные специализации для 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 2119 | C++11 | специализации для расширенных целочисленных типов отсутствовали | добавлены |
| 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/cpp/utility/hash