diff --git a/reference/functional/hash.md b/reference/functional/hash.md index f1b626178..764b4ff5c 100644 --- a/reference/functional/hash.md +++ b/reference/functional/hash.md @@ -36,9 +36,11 @@ namespace std { ## 概要 クラステンプレート`hash`は、非順序連想コンテナ([`unordered_map`](/reference/unordered_map/unordered_map.md)/[`unordered_multimap`](/reference/unordered_map/unordered_multimap.md)/[`unordered_set`](/reference/unordered_set/unordered_set.md)/[`unordered_multiset`](/reference/unordered_set/unordered_multiset.md))のキーとなる型のためのハッシュ値を計算する関数オブジェクトである。 -このクラスはそのものにデフォルトの定義は存在せず、ユーザーが任意の型で特殊化する際の要件を定義する。`hash`クラステンプレートを特殊化する場合、以下に記述するメンバ関数を持たせる必要がある。 +このクラスはそのものにデフォルトの定義は存在せず、ユーザーが任意の型で特殊化する際の要件を定義する。`hash`クラステンプレートを特殊化する場合、後述するメンバ関数を持たせる必要がある。 -``ヘッダでは、以下の特殊化を提供する。これ以外の特殊化は、対象型を定義する各種ヘッダファイルにて提供される: +### 基本型のハッシュサポート +``ヘッダでは、基本型に対する特殊化を提供する。 +`std::string`などC++標準ライブラリ定義の型に対する特殊化は、対象型を定義する各種ヘッダファイルにて提供される。 | 型 | 対応バージョン | |----------------------|----------------| @@ -69,18 +71,25 @@ namespace std { ## メンバ関数 | 名前 | 説明 | -|-----------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------| -| `hash()`
`hash(const hash&)`
`hash(hash&&)` | デフォルトコンストラクタ、コピーコンストラクタ、ムーブコンストラクタを持つ | -| `~hash()` | デストラクタを持つ | -| `hash& operator=(const hash&)`
`hash& operator=(hash&&)` | コピー代入演算子とムーブ代入演算子を持つ | -| `size_t operator()(T key) const` | 関数呼び出し演算子によって、キーに対応するハッシュ値を返す | +|------|------| +| `(constructor)` | デフォルトコンストラクタ、コピーコンストラクタ、ムーブコンストラクタを持つ | +| `(destructor)` | デストラクタを持つ | +| `operator=` | コピー代入演算子とムーブ代入演算子を持つ | +| `operator()` | 関数呼び出し演算子によって、キー値`k`に対応する`size_t`型のハッシュ値を返す。`const`修飾メンバ関数。 | + +関数呼び出し演算子に関する制約は次の通り : + +- 引数に指定するキー値`k`を変更してはならない。 +- ハッシュ計算は引数で指定したキー値以外に依存してはいけない(状態をもってはいけない)。 +- 式`k1 == k2`を満たす2個のキー値に対しては、同一ハッシュ値を返すこと。 + - 異なる2個のキーに対して同一ハッシュ値を返すこと(collision; 衝突)は許容されるが、入力に対する出力ハッシュ値は`size_t`型の値域において均等分布することが好ましい。 ## メンバ型 | 名前 | 説明 | 対応バージョン | |------|------|----------------| -| `is_transparent` | 省略可。ハッシュ計算の関数オブジェクトがこの型を持っている場合、非順序連想コンテナの透過的な検索関数が有効になる。
この型は、例として`hash`が`hash`や`hash`と等価なハッシュ値を生成できるような場合に定義される。 | C++20 | +| `is_transparent` | 省略可。ハッシュ計算を行う関数オブジェクトがこの型を持っている場合、非順序連想コンテナの透過的な検索関数が有効になる。
この型は、例えば関数オブジェクトが`string`型/`string_view`型/ヌル終端文字列(`const char*`)に対して等価なハッシュ値を生成できる場合に定義される。 | C++20 | ## 例 @@ -89,6 +98,8 @@ namespace std { #include #include +enum class E { A = 1, B = 42, C = 100 }; + int main() { int x; @@ -104,6 +115,10 @@ int main() // int*型のアドレス値(&x)に対するハッシュ値を求める std::cout << std::hash()(&x) << std::endl; + + // 列挙型の値E::Bに対するハッシュ値を求める(C++14から) + E e = E::B; + std::cout << std::hash()(e) << std::endl; } ``` * std::hash[color ff0000] @@ -114,10 +129,11 @@ int main() 100 1427109137 3219530756 +42 ``` ### 透過的にハッシュ値を計算できる場合 (C++20) -`is_transparent`が定義される場合、以下のようなコードにおいて、`find()`メンバ関数に文字列リテラルを指定しても、一時的な[`string`](/reference/string/basic_string.md)オブジェクトが作成されず、パフォーマンス向上が期待できる。 +メンバ型`is_transparent`が定義される場合、以下のようなコードにおいて、[`find`](/reference/unordered_map/unordered_map/find.md)メンバ関数に文字列リテラルを指定しても、一時的な[`string`](/reference/string/basic_string.md)オブジェクトが作成されず、パフォーマンス向上が期待できる。 ```cpp example #include @@ -135,6 +151,7 @@ struct string_hash { int main() { + // キー型=std::string, 値型=int std::unordered_map> um = { {"Alice", 3}, {"Bob", 1}, @@ -142,7 +159,7 @@ int main() }; // string_hashおよびstd::equal_to<>はいずれもメンバ型にis_transparentを持つため、 - // find()などの検索関数に引数を渡す場合に、std::string一時オブジェクトが作られない + // find()などの検索関数に値を渡す場合に、キー型(std::string)一時オブジェクトが作られない auto it = um.find("Alice"); if (it != um.end()) { std::cout << "found : " << it->second << std::endl; @@ -189,7 +206,9 @@ found : 3 ## 参照 - [ハッシュ関数 - Wikipedia](https://ja.wikipedia.org/wiki/ハッシュ関数) -- [LWG 2148 - Hashing enums should be supported directly by std::hash](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2148) +- [LWG 2148 - Hashing enums should be supported directly by `std::hash`](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2148) - [LWG 2291 - std::hash is vulnerable to collision DoS attack](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2291) +- [LWG 2543 - LWG 2148 (hash support for enum types) seems under-specified](https://cplusplus.github.io/LWG/issue2543) +- [LWG 2817 - `std::hash` for `nullptr_t`](https://cplusplus.github.io/LWG/issue2817) - [P0919R3 Heterogeneous lookup for unordered containers](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0919r3.html) - [P1690R1 Refinement Proposal for P0919 Heterogeneous lookup for unordered containers](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1690r1.html)