std::hash
ヘッダ <functional> で定義 | ||
template<class Key > struct hash; | (C++11以上) | |
このテンプレートの各々の特殊化は有効 (「汚染されていない」) または無効 (「汚染されている」) のいずれかです。 有効な | (C++17以上) |
hash テンプレートの有効な特殊化(C++17以上)はハッシュ関数を実装する関数オブジェクトを定義します。 この関数オブジェクトのインスタンスは Hash を満たします。 特に、この型は以下のような operator()const を定義します。
1. Key
型の引数を1つ取ります。
2. 引数のハッシュ値を表す std::size_t 型の値を返します。
3. 呼ばれた時に例外を投げることはありません。
4. 2つの等しい値 k1
および k2
に対して、 std::hash<Key>()(k1)== std::hash<Key>()(k2) です。
5. 2つの等しくない異なる値 k1
および k2
に対して、 std::hash<Key>()(k1)== std::hash<Key>()(k2) である確率が非常に小さい、具体的には 1.0/std::numeric_limits<std::size_t>::max() に近いことが期待されます。
標準ライブラリによって提供される hash
の明示的および部分的なすべての特殊化は DefaultConstructible、 CopyAssignable、 Swappable、 Destructible を満たします。 ユーザが提供する hash
の特殊化もこれらの要件を満たさなければなりません。
非順序連想コンテナ std::unordered_set、 std::unordered_multiset、 std::unordered_map、 std::unordered_multimap はデフォルトのハッシュ関数として std::hash テンプレートの特殊化を使用します。
目次 |
[編集]ノート
実際のハッシュ関数は処理系依存であり、上で規定されている以外のいかなる品質基準も満たすことは要求されません。 例えば、整数をそれ自身に対応付ける自明な (恒等な) ハッシュ関数を使っている処理系もあります。 別の言い方をすると、これらのハッシュ関数は非順序連想コンテナで使えるようには設計されていますが、例えば、暗号学的なハッシュとしては使用できません。
ハッシュ関数は、単一のプログラム実行中でしか、同じ入力に対して同じ結果を返すことが要求されません。 これにより、衝突サービス拒否攻撃を防ぐソルト付きのハッシュを使うことができます。 | (C++14以上) |
C の文字列に対する特殊化はありません。 std::hash<constchar*> はポインタの値 (メモリアドレス) のハッシュを返し、文字配列の内容は考慮しません。
メンバ型
| (C++20未満) |
[編集]メンバ関数
ハッシュ関数オブジェクトを構築します (パブリックメンバ関数) | |
引数のハッシュを計算します (パブリックメンバ関数) |
[編集]基本型に対する標準の特殊化
ヘッダ <functional> で定義 | ||
template<>struct hash<bool>; template<>struct hash<char>; | ||
上記に加え、すべての (スコープ付きおよびスコープなしの) 列挙型に対する特殊化も標準ライブラリによって提供されます。 これらは std::hash<std::underlying_type<Enum>::type> として実装されるかもしれません (が、要求されているわけではありません)。 | (C++14以上) |
テンプレート このテンプレートの標準ライブラリによるすべての特殊化のすべてのメンバ関数は noexcept です。 ただし std::hash<std::optional>、 std::hash<std::variant>、 std::hash<std::unique_ptr> は除きます。 | (C++17以上) |
[編集]ライブラリ型に対する標準の特殊化
(C++11)(C++20)(C++11)(C++11)(C++11)(C++20)(C++20)(C++20)(C++20)(C++20) | 文字列に対するハッシュサポート (クラステンプレートの特殊化) |
(C++11) | std::error_code に対するハッシュサポート (クラステンプレートの特殊化) |
(C++11) | std::bitset に対するハッシュサポート (クラステンプレートの特殊化) |
(C++11) | std::unique_ptr に対するハッシュサポート (クラステンプレートの特殊化) |
(C++11) | std::shared_ptr に対するハッシュサポート (クラステンプレートの特殊化) |
(C++11) | std::type_index に対するハッシュサポート (クラステンプレートの特殊化) |
(C++11) | std::vector<bool> に対するハッシュサポート (クラステンプレートの特殊化) |
(C++11) | std::thread::id に対するハッシュサポート (クラステンプレートの特殊化) |
(C++17) | std::hash アルゴリズムの特殊化 (クラステンプレートの特殊化) |
(C++17) | std::hash アルゴリズムの特殊化 (クラステンプレートの特殊化) |
文字列ビューに対するハッシュサポート (クラステンプレートの特殊化) | |
std::error_condition に対するハッシュサポート (クラステンプレートの特殊化) |
ノート: std::pair
および標準のコンテナ型に対する追加の特殊化やハッシュを合成するユーティリティ関数が boost.hash で利用可能です。
[編集]例
#include <iostream>#include <iomanip>#include <functional>#include <string>#include <unordered_set> struct S {std::string first_name;std::string last_name;};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()(S const& s)constnoexcept{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 名前空間に注入できます。namespace std {template<>struct hash<S>{std::size_t operator()(S const& s)constnoexcept{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)<<") = "<< str_hash <<'\n'; S obj ={"Hubert", "Farnsworth"};// スタンドアロンの関数オブジェクトを使用。std::cout<<"hash("<<std::quoted(obj.first_name)<<','<<std::quoted(obj.last_name)<<") = "<< MyHash{}(obj)<<" (using MyHash)\n or "<< std::hash<S>{}(obj)<<" (using injected std::hash<S> specialization)\n"; // カスタムハッシュにより非順序コンテナでカスタム型が使用できるようになります。// この例では上の注入された std::hash<S> の特殊化を使用します。// 代わりに MyHash を使う場合は、それを第2テンプレート引数として渡してください。std::unordered_set<S> names ={obj, {"Bender", "Rodriguez"}, {"Turanga", "Leela"}};for(auto& s: names)std::cout<<std::quoted(s.first_name)<<' '<<std::quoted(s.last_name)<<'\n';}
出力例:
hash("Meet the new boss...") = 1861821886482076440 hash("Hubert","Farnsworth") = 17622465712001802105 (using MyHash) or 17622465712001802105 (using injected std::hash<S> specialization) "Turanga" "Leela" "Bender" "Rodriguez" "Hubert" "Farnsworth"