Namespaces
Variants

std::hash

From ja.cppreference.net
 
 
ユーティリティライブラリ
言語サポート
型サポート (基本型、RTTI)
ライブラリ機能テストマクロ (C++20)
プログラムユーティリティ
可変引数関数
コルーチンサポート (C++20)
契約サポート (C++26)
三方比較
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

汎用ユーティリティ
関係演算子 (C++20で非推奨)
整数比較関数
(C++20)(C++20)(C++20)    
(C++20)
Swapp と 型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
共通語彙型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)



 
 
ヘッダ <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> は有効(enabled) または 無効(disabled)  のいずれかです:

  • もし 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 です:

  • 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まで)

メンバー関数

ハッシュ関数オブジェクトを構築する
(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 の特殊化が欠如していた 提供された