Namespaces
Variants

std:: hash

From cppreference.net
Utilities library
Определено в заголовке <bitset>
Определено в заголовке <coroutine>
(начиная с C++20)
Определено в заголовке <chrono>
(начиная с C++26)
Определено в заголовке <filesystem>
(начиная с C++17)
Определено в заголовке <functional>
Определено в заголовке <memory>
Определено в заголовке <optional>
(начиная с C++17)
Определено в заголовке <stacktrace>
(начиная с C++23)
Определено в заголовке <string>
Определено в заголовке <string_view>
(начиная с C++17)
Определено в заголовке <system_error>
Определено в заголовке <text_encoding>
(начиная с C++26)
Определено в заголовке <thread>
Определено в заголовке <typeindex>
Определено в заголовке <utility>
(начиная с C++26)
Определено в заголовке <variant>
(начиная с C++17)
Определено в заголовке <vector>
template < class Key >
struct hash ;
(начиная с C++11)

Включенные специализации шаблона hash определяют функциональный объект, который реализует хеш-функцию .

Для заданного типа Key каждая специализация std::hash<Key> может быть включена или отключена :

  • Если std::hash<Key> не предоставлен программой или пользователем, он отключен.
  • В противном случае, std::hash<Key> включен при выполнении всех следующих условий:
  • Выполнены все следующие требования:
  • Даны следующие значения:
  • h - объект типа std::hash<Key> .
  • k1 и k2 - объекты типа Key .
Выполнены все следующие требования:
  • В противном случае, std::hash<Key> отключен.

Отключенные специализации не удовлетворяют Hash , не удовлетворяют FunctionObject , и следующие значения являются false :

**Примечание:** Весь текст внутри HTML-тегов и C++ код оставлены без изменений в соответствии с инструкциями. В данном фрагменте отсутствует текст для перевода за пределами тегов программирования.

Другими словами, они существуют, но не могут быть использованы.

Содержание

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

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

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

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

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

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

Автономная реализация обязана предоставлять указанные выше специализации и отключённые по умолчанию специализации.

(начиная с C++20)

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

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

(since C++26)
(since C++17)

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

Библиотека поддержки языка
поддержка хеширования для std::coroutine_handle
(специализация шаблона класса)
Библиотека диагностики
поддержка хеширования для std::error_code
(специализация шаблона класса)
поддержка хеширования для std::error_condition
(специализация шаблона класса)
Поддержка хеширования для std::type_index
(специализация шаблона класса)
поддержка хеширования для std::stacktrace_entry
(специализация шаблона класса)
поддержка хеширования для std::basic_stacktrace
(специализация шаблона класса)
Библиотека управления памятью
поддержка хеширования для std::unique_ptr
(специализация шаблона класса)
поддержка хеширования для std::shared_ptr
(специализация шаблона класса)
поддержка хеширования для std::indirect
(специализация шаблона класса)
Библиотека общих утилит
поддержка хеширования для std::optional
(специализация шаблона класса)
поддержка хеширования для std::variant
(специализация шаблона класса)
поддержка хеширования для std::monostate
(специализация шаблона класса)
поддержка хеширования для std::bitset
(специализация шаблона класса)
Библиотека контейнеров
поддержка хеширования для std::vector<bool>
(специализация шаблона класса)
Библиотека строк
поддержка хеширования для строк
(специализация шаблона класса)
поддержка хеширования для строковых представлений
(специализация шаблона класса)
Библиотека обработки текста
поддержка хеширования для std::text_encoding
(специализация шаблона класса)
Библиотека времени
поддержка хеширования для std::chrono::duration
(специализация шаблона класса)
поддержка хеширования для std::chrono::time_point
(специализация шаблона класса)
поддержка хеширования для std::chrono::day
(специализация шаблона класса)
поддержка хеширования для std::chrono::month
(специализация шаблона класса)
поддержка хеширования для std::chrono::year
(специализация шаблона класса)
поддержка хеширования для std::chrono::weekday
(специализация шаблона класса)
поддержка хеширования для std::chrono::weekday_indexed
(специализация шаблона класса)
поддержка хеширования для std::chrono::weekday_last
(специализация шаблона класса)
поддержка хеширования для std::chrono::month_day
(специализация шаблона класса)
поддержка хеширования для std::chrono::month_day_last
(специализация шаблона класса)
поддержка хеширования для std::chrono::month_weekday
(специализация шаблона класса)
поддержка хеширования для std::chrono::month_weekday_last
(специализация шаблона класса)
поддержка хеширования для std::chrono::year_month
(специализация шаблона класса)
поддержка хеширования для std::chrono::year_month_day
(специализация шаблона класса)
поддержка хеширования для std::chrono::year_month_day_last
(специализация шаблона класса)
поддержка хеширования для std::chrono::year_month_weekday
(специализация шаблона класса)
поддержка хеширования для std::chrono::year_month_weekday_last
(специализация шаблона класса)
поддержка хеширования для std::chrono::zoned_time
(специализация шаблона класса)
поддержка хеширования для std::chrono::leap_second
(специализация шаблона класса)
Библиотека ввода/вывода
Поддержка хеширования для std::filesystem::path
(специализация шаблона класса)
Библиотека поддержки многопоточности
Поддержка хеширования для std::thread::id
(специализация шаблона класса)

Примечания

Фактические хеш-функции зависят от реализации и не обязаны соответствовать каким-либо иным критериям качества, кроме указанных выше. В частности, некоторые реализации используют тривиальные (тождественные) хеш-функции, которые отображают целое число в само себя. Иными словами, эти хеш-функции предназначены для работы с неупорядоченными ассоциативными контейнерами, но не в качестве криптографических хешей, например.

Хеш-функции обязаны производить одинаковый результат для одинаковых входных данных только в пределах одного выполнения программы; это позволяет использовать соленые хеши, которые предотвращают атаки отказа в обслуживании через коллизии.

Для C-строк не предусмотрена специализация. std :: hash < const char * > создаёт хеш значения указателя (адреса памяти) и не анализирует содержимое символьного массива.

Дополнительные специализации для 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; // начиная с C++20
};
// До C++20.
// bool operator==(const S& lhs, const S& rhs)
// {
//     return lhs.first_name == rhs.first_name && lhs.last_name == rhs.last_name;
// }
// Пользовательский хэш может быть автономным функциональным объектом.
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); // или использовать boost::hash_combine
    }
};
// Пользовательская специализация std::hash может быть внедрена в пространство имен 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); // или использовать 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"};
    // Использование автономного функционального объекта.
    std::cout << "hash(" << std::quoted(obj.first_name) << ", "
              << std::quoted(obj.last_name) << ") =\t"
              << MyHash{}(obj) << " (используя MyHash) или\n\t\t\t\t"
              << std::hash<S>{}(obj) << " (используя внедренную специализацию)\n";
    // Пользовательский хэш позволяет использовать пользовательские типы в неупорядоченных контейнерах.
    // Пример будет использовать внедренную специализацию std::hash<S> выше,
    // чтобы использовать MyHash вместо этого, передайте его вторым аргументом шаблона.
    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) или
                                12922914235676820612 (using injected specialization)
"Bender" "Rodriguez"
"Turanga" "Leela"
"Hubert" "Farnsworth"

Отчёты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
LWG 2119 C++11 специализации для расширенных целочисленных типов отсутствовали предоставлены
LWG 2148 C++11 специализации для перечислений отсутствовали предоставлены
LWG 2543 C++11 std::hash может не быть SFINAE-friendly сделано SFINAE-friendly
LWG 2817 C++11 специализация для std::nullptr_t отсутствовала предоставлена