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> は有効 (enabled) または無効 (disabled) のいずれかです。
std::hash<Key>がプログラムまたはユーザーによって提供されない場合、それは無効です。- そうでない場合、以下の条件がすべて満たされれば
std::hash<Key>は有効です。
- 以下の要件がすべて満たされている
- Hash (関数呼び出しの引数型として
Keyを使用) - DefaultConstructible
- CopyAssignable
- Swappable
- Hash (関数呼び出しの引数型として
- 以下の値が与えられたとする
- h、型
std::hash<Key>のオブジェクト。 - k1 と k2、型
Keyのオブジェクト。
- h、型
- 以下の要件がすべて満たされている
- 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
言い換えると、それらは存在しますが、使用することはできません。
ネストされた型
|
(C++20まで) |
[編集] メンバ関数
| ハッシュ関数オブジェクトを構築する (public member function) | |
| 引数のハッシュ値を計算する (public member function) |
[編集] 標準ライブラリの特殊化
テンプレート std::hash を宣言する各ヘッダーは、以下の型に対して有効化された std::hash の特殊化も提供します。
- すべてのcv修飾されていない算術型
- すべてのcv修飾されていない列挙型
- すべてのcv修飾されていないポインタ型
- std::nullptr_t
それに加えて、一部のヘッダーはライブラリ型に対して他の有効化された std::hash 特殊化も提供します(下記を参照)。
|
標準ライブラリによって提供されるすべての
|
(C++17以降) |
[編集] ライブラリ型に対する特殊化
| std::coroutine_handle のハッシュサポート (クラステンプレートの特殊化) | |
| (C++11) |
std::error_code のハッシュサポート (クラステンプレートの特殊化) |
| std::error_condition のハッシュサポート (クラステンプレートの特殊化) | |
| std::stacktrace_entry のハッシュサポート (クラステンプレートの特殊化) | |
| std::basic_stacktrace のハッシュサポート (クラステンプレートの特殊化) | |
| (C++17) |
std::optional のハッシュサポート (class template specialization) |
| (C++17) |
std::variant のハッシュサポート (クラステンプレートの特殊化) |
| (C++17) |
std::monostate のハッシュサポート (クラステンプレートの特殊化) |
| (C++11) |
std::bitset のハッシュサポート (class template specialization) |
| (C++11) |
std::unique_ptr のハッシュサポート (クラステンプレートの特殊化) |
| (C++11) |
std::shared_ptr のハッシュサポート (クラステンプレートの特殊化) |
| (C++11) |
std::type_index のハッシュサポート (クラステンプレートの特殊化) |
| (C++11) |
文字列のハッシュサポート (クラステンプレートの特殊化) |
| 文字列ビューのハッシュサポート (クラステンプレートの特殊化) | |
| std::text_encoding のハッシュサポート (クラステンプレートの特殊化) | |
| (C++11) |
std::vector<bool> のハッシュサポート (クラステンプレートの特殊化) |
| std::filesystem::path のハッシュサポート (クラステンプレートの特殊化) | |
| (C++11) |
std::thread::id のハッシュサポート (クラステンプレートの特殊化) |
| std::chrono::duration のハッシュサポート (クラステンプレートの特殊化) | |
| std::chrono::time_point のハッシュサポート (クラステンプレートの特殊化) | |
| (C++26) |
std::chrono::day のハッシュサポート (クラステンプレートの特殊化) |
| std::chrono::month のハッシュサポート (クラステンプレートの特殊化) | |
| (C++26) |
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 に対する特殊化が欠けていた | 提供された |