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 型のオブジェクト
以下の要件をすべて満たすこと:
  • k1 == k2 true の場合、 h ( k1 ) == h ( k2 ) true となること
  • std::hash<Key> プログラム定義の特殊化 でない限り、 h ( k1 ) は例外を送出しないこと
  • それ以外の場合、 std::hash<Key> は無効化されます。

無効化された特殊化は Hash を満たさず、 FunctionObject を満たさず、以下の値はすべて false となります:

言い換えれば、それらは存在するが使用することはできません。

目次

ネスト型

定義
argument_type (C++17で非推奨) Key
result_type (C++17で非推奨) std::size_t
(C++20まで)

メンバー関数

ハッシュ関数オブジェクトを構築する
(public member function)
引数のハッシュ値を計算する
(public member function)

標準ライブラリ特殊化

std::hash テンプレートを宣言する各ヘッダーは、 以下の型に対して有効化された std::hash の特殊化も提供します:

フリースタンディング実装 は、前述の特殊化とデフォルトで無効化されている特殊化を提供することが要求される。

(C++20以降)

さらに、一部のヘッダーはライブラリ型に対するその他の有効な std::hash 特殊化も提供しています( 下記 を参照)。

標準ライブラリが提供する全ての std::hash 特殊化について、以下のものを除き、全てのメンバ関数は noexcept です:

(C++26以降)
(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::monostate
(クラステンプレートの特殊化)
std::bitset のハッシュサポート
(クラステンプレートの特殊化)
コンテナライブラリ
std::vector<bool>のハッシュサポート 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
(クラステンプレートの特殊化)
std::chrono::weekday_indexed のハッシュサポート
(クラステンプレートの特殊化)
std::chrono::weekday_last のハッシュサポート
(クラステンプレートの特殊化)
std::chrono::month_day のハッシュサポート
(クラステンプレートの特殊化)
std::chrono::month_day_lastのハッシュサポート 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
(クラステンプレートの特殊化)
std::chrono::year_month_day_last のハッシュサポート 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を使用する場合は、第2テンプレート引数として渡す
    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 適用対象 公開時の動作 正しい動作
LWG 2119 C++11 拡張整数型の特殊化が欠如していた 提供された
LWG 2148 C++11 列挙型の特殊化が欠如していた 提供された
LWG 2543 C++11 std::hash SFINAEフレンドリーではない可能性があった SFINAEフレンドリーに変更された
LWG 2817 C++11 std::nullptr_t の特殊化が欠如していた 提供された