Spec-Zone.ru › C++

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>>::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

Иными словами, они существуют, но их нельзя использовать.

Вложенные типы

Тип Определение
argument_type (устарело в C++17) Key
result_type (устарело в C++17) std::size_t
(до C++20)

Функции-члены

(конструктор)
создаёт объект хеш-функции
(открытая функция-член)
operator()
вычисляет хеш аргумента
(открытая функция-член)

Специализации стандартной библиотеки

Каждый заголовочный файл, объявляющий шаблон std::hash, также предоставляет включённые специализации std::hash для следующих типов:

  • все арифметические типы без cv-квалификаторов
  • все типы перечислений без cv-квалификаторов
  • все типы указателей без cv-квалификаторов
  • std::nullptr_t

Кроме того, некоторые заголовочные файлы предоставляют другие включённые специализации std::hash для библиотечных типов (см. ниже).

Для всех специализаций std::hash, предоставляемых стандартной библиотекой, кроме перечисленных ниже, все функции-члены имеют спецификатор noexcept:

  • std::hash<std::optional>
  • std::hash<std::variant>
  • std::hash<std::unique_ptr>
  • std::hash<std::indirect>
  • std::hash<std::chrono::duration>
  • std::hash<std::chrono::time_point>
  • std::hash<std::chrono::zoned_time>
(начиная с C++26)
(начиная с C++17)

Специализации для библиотечных типов

Библиотека поддержки языка
std::hash<std::coroutine_handle>
(C++20)
поддержка хеширования для std::coroutine_handle
(специализация шаблона класса)
Библиотека диагностики
std::hash<std::error_code>
(C++11)
поддержка хеширования для std::error_code
(специализация шаблона класса)
std::hash<std::error_condition>
(C++17)
поддержка хеширования для std::error_condition
(специализация шаблона класса)
std::hash<std::type_index>
(C++11)
поддержка хеширования для std::type_index
(специализация шаблона класса)
std::hash<std::stacktrace_entry>
(C++23)
поддержка хеширования для std::stacktrace_entry
(специализация шаблона класса)
std::hash<std::basic_stacktrace>
(C++23)
поддержка хеширования для std::basic_stacktrace
(специализация шаблона класса)
Библиотека управления памятью
std::hash<std::unique_ptr>
(C++11)
поддержка хеширования для std::unique_ptr
(специализация шаблона класса)
std::hash<std::shared_ptr>
(C++11)
поддержка хеширования для std::shared_ptr
(специализация шаблона класса)
std::hash<std::indirect>
(C++26)
поддержка хеширования для std::indirect
(специализация шаблона класса)
Библиотека общих утилит
std::hash<std::optional>
(C++17)
поддержка хеширования для std::optional
(специализация шаблона класса)
std::hash<std::variant>
(C++17)
поддержка хеширования для std::variant
(специализация шаблона класса)
std::hash<std::monostate>
(C++17)
поддержка хеширования для std::monostate
(специализация шаблона класса)
std::hash<std::bitset>
(C++11)
поддержка хеширования для std::bitset
(специализация шаблона класса)
Библиотека контейнеров
std::hash<std::vector<bool>>
(C++11)
поддержка хеширования для std::vector<bool>
(специализация шаблона класса)
Библиотека строк
std::hash<std::basic_string>
(C++11)
поддержка хеширования для строк
(специализация шаблона класса)
std::hash<std::string_view>std::hash<std::wstring_view>std::hash<std::u8string_view>std::hash<std::u16string_view>std::hash<std::u32string_view>
(C++17)(C++17)(C++20)(C++17)(C++17)
поддержка хеширования для представлений строк
(специализация шаблона класса)
Библиотека обработки текста
std::hash<std::text_encoding>
(C++26)
поддержка хеширования для std::text_encoding
(специализация шаблона класса)
Библиотека измерения времени
std::hash<std::chrono::duration>
(C++26)
поддержка хеширования для std::chrono::duration
(специализация шаблона класса)
std::hash<std::chrono::time_point>
(C++26)
поддержка хеширования для std::chrono::time_point
(специализация шаблона класса)
std::hash<std::chrono::day>
(C++26)
поддержка хеширования для std::chrono::day
(специализация шаблона класса)
std::hash<std::chrono::month>
(C++26)
поддержка хеширования для std::chrono::month
(специализация шаблона класса)
std::hash<std::chrono::year>
(C++26)
поддержка хеширования для std::chrono::year
(специализация шаблона класса)
std::hash<std::chrono::weekday>
(C++26)
поддержка хеширования для std::chrono::weekday
(специализация шаблона класса)
std::hash<std::chrono::weekday_indexed>
(C++26)
поддержка хеширования для std::chrono::weekday_indexed
(специализация шаблона класса)
std::hash<std::chrono::weekday_last>
(C++26)
поддержка хеширования для std::chrono::weekday_last
(специализация шаблона класса)
std::hash<std::chrono::month_day>
(C++26)
поддержка хеширования для std::chrono::month_day
(специализация шаблона класса)
std::hash<std::chrono::month_day_last>
(C++26)
поддержка хеширования для std::chrono::month_day_last
(специализация шаблона класса)
std::hash<std::chrono::month_weekday>
(C++26)
поддержка хеширования для std::chrono::month_weekday
(специализация шаблона класса)
std::hash<std::chrono::month_weekday_last>
(C++26)
поддержка хеширования для std::chrono::month_weekday_last
(специализация шаблона класса)
std::hash<std::chrono::year_month>
(C++26)
поддержка хеширования для std::chrono::year_month
(специализация шаблона класса)
std::hash<std::chrono::year_month_day>
(C++26)
поддержка хеширования для std::chrono::year_month_day
(специализация шаблона класса)
std::hash<std::chrono::year_month_day_last>
(C++26)
поддержка хеширования для std::chrono::year_month_day_last
(специализация шаблона класса)
std::hash<std::chrono::year_month_weekday>
(C++26)
поддержка хеширования для std::chrono::year_month_weekday
(специализация шаблона класса)
std::hash<std::chrono::year_month_weekday_last>
(C++26)
поддержка хеширования для std::chrono::year_month_weekday_last
(специализация шаблона класса)
std::hash<std::chrono::zoned_time>
(C++26)
поддержка хеширования для std::chrono::zoned_time
(специализация шаблона класса)
std::hash<std::chrono::leap_second>
(C++26)
поддержка хеширования для std::chrono::leap_second
(специализация шаблона класса)
Библиотека ввода-вывода
std::hash<std::filesystem::path>
(C++17)
поддержка хеширования для std::filesystem::path
(специализация шаблона класса)
Библиотека поддержки параллелизма
std::hash<std::thread::id>
(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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API