名前空間
変種
操作

std::hash

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

汎用ユーティリティ
関係演算子 (C++20で非推奨)
 
 
ヘッダー <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> のオブジェクト。
  • k1k2、型 Key のオブジェクト。
以下の要件がすべて満たされている
  • k1 == k2true である場合、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 の特殊化も提供します。

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

標準ライブラリによって提供されるすべての std::hash 特殊化のうち、以下を除くすべてのメンバ関数は noexcept です。

(C++26以降)
(C++17以降)

[編集] ライブラリ型に対する特殊化

std::coroutine_handle のハッシュサポート
(クラステンプレートの特殊化) [編集]
std::error_code のハッシュサポート
(クラステンプレートの特殊化) [編集]
std::error_condition のハッシュサポート
(クラステンプレートの特殊化) [編集]
std::stacktrace_entry のハッシュサポート
(クラステンプレートの特殊化) [編集]
std::basic_stacktrace のハッシュサポート
(クラステンプレートの特殊化) [編集]
std::optional のハッシュサポート
(class template specialization) [編集]
std::variant のハッシュサポート
(クラステンプレートの特殊化) [編集]
std::monostate のハッシュサポート
(クラステンプレートの特殊化)
std::bitset のハッシュサポート
(class template specialization) [編集]
std::unique_ptr のハッシュサポート
(クラステンプレートの特殊化) [編集]
std::shared_ptr のハッシュサポート
(クラステンプレートの特殊化) [編集]
std::type_index のハッシュサポート
(クラステンプレートの特殊化) [編集]
文字列のハッシュサポート
(クラステンプレートの特殊化) [編集]
文字列ビューのハッシュサポート
(クラステンプレートの特殊化) [編集]
std::text_encoding のハッシュサポート
(クラステンプレートの特殊化) [編集]
std::vector<bool> のハッシュサポート
(クラステンプレートの特殊化)
std::filesystem::path のハッシュサポート
(クラステンプレートの特殊化) [編集]
std::thread::id のハッシュサポート
(クラステンプレートの特殊化) [編集]
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 のハッシュサポート
(クラステンプレートの特殊化)

[編集] 注釈

実際のハッシュ関数は実装依存であり、上記で指定された以外の品質基準を満たすことは要求されません。特に、一部の実装では整数をそれ自体にマップする簡単な(恒等)ハッシュ関数を使用します。言い換えれば、これらのハッシュ関数は非順序連想コンテナで動作するように設計されていますが、例えば暗号学的ハッシュとして使用するようには設計されていません。

ハッシュ関数は、プログラムの単一の実行内で同じ入力に対して同じ結果を生成することのみが要求されます。これにより、衝突によるサービス拒否攻撃を防ぐためのソルト付きハッシュが可能になります。

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; // 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 に対する特殊化が欠けていた 提供された
English 日本語 中文(简体) 中文(繁體)