This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.

### 2109. Incorrect requirements for `hash` specializations

Section: 19.5.7 [syserr.hash], 20.11.7 [util.smartptr.hash], 20.14.19 [unord.hash], 20.17.1 [type.index.synopsis], 21.3.6 [basic.string.hash], 22.3.12 [vector.bool], 32.4.3.2 [thread.thread.id] Status: C++14 Submitter: Daniel Krügler Opened: 2011-12-04 Last modified: 2016-01-28

Priority: Not Prioritized

View all issues with C++14 status.

Discussion:

20.11.7 [util.smartptr.hash] p2 is specified as follows:

> Requires: the template specializations shall meet the requirements of class template `hash` (20.8.12).

The problem here is the usage of a Requires element, which is actually a pre-condition that a user of a component has to satisfy. But the intent of this wording is actually to be a requirement on implementations. The Requires element should be removed here and the wording should be improved to say what it was intended for.

We have similar situations in basically all other places where the specification of library-provided `hash` specializations is defined. Usually, the Requires element is incorrect. In the special case of `hash<unique_ptr<T, D>>` the implementation depends on the behaviour of `hash` specializations, that could be user-provided. In this case the specification needs to separate the requirements on these specializations and those that are imposed on the implementation.

[2012, Kona]

Update wording and move to Review.

Believe a simpler formulation is to simply string the term Requires: and leave the current wording intact, rather than strike the whole clause and replace it.

[Originally proposed wording for reference

1. Change 19.5.7 [syserr.hash] as indicated:

   >     template <> struct hash<error_code>;

   > > -1- Requires: the template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash])The header `<system_error>` provides a definition for a specialization of the template `hash<error_code>`. The requirements for the members of this specialization are given in sub-clause 20.14.19 [unord.hash].

2. Change 20.9.3 [bitset.hash] as indicated:

   >     template <size_t N> struct hash<bitset<N> >;

   > > -1- Requires: the template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash])The header `<bitset>` provides a definition for a partial specialization of the `hash` class template for specializations of class template `bitset<N>`. The requirements for the members of instantiations of this specialization are given in sub-clause 20.14.19 [unord.hash].

3. Change 20.11.7 [util.smartptr.hash] as indicated:

   >     template <class T, class D> struct hash<unique_ptr<T, D> >;

   > > -1- Requires: the template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash])The header `<memory>` provides a definition for a partial specialization of the `hash` class template for specializations of class template `unique_ptr<T, D>`. The requirements for the members of instantiations of this specialization are given in sub-clause 20.14.19 [unord.hash]. For an object `p` of type `UP`, where `UP` is `unique_ptr<T, D>`, `hash<UP>()(p)` shall evaluate to the same value as `hash<typename UP::pointer>()(p.get())`. The specialization `hash<typename UP::pointer>` shall be well-formed.

   > > -?- Requires: The specialization `hash<typename UP::pointer>` shall be well-formed and well-defined [Note: the general requirements of class template `hash` (20.14.19 [unord.hash]) are implied — end note].

   >     template <class T> struct hash<shared_ptr<T> >;

   > > -2- Requires: the template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash])The header `<memory>` provides a definition for a partial specialization of the `hash` class template for specializations of class template `shared_ptr<T>`. The requirements for the members of instantiations of this specialization are given in sub-clause 20.14.19 [unord.hash]. For an object `p` of type `shared_ptr<T>`, `hash<shared_ptr<T> >()(p)` shall evaluate to the same value as `hash<T*>()(p.get())`.

4. Change 20.14.19 [unord.hash] p2 as indicated: [Comment: For unknown reasons the extended integer types are not mentioned here, which looks like an oversight to me and makes also the wording more complicated. See 2119 for this part of the problem. — end comment]

   >     template <> struct hash<bool>;
   >     template <> struct hash<char>;
   >     […]
   >     template <> struct hash<long double>;
   >     template <class T> struct hash<T*>;

   > > -2- Requires: the template specializations shall meet the requirements of class template `hash` (20.14.19 [unord.hash])The header `<functional>` provides definitions for specializations of the `hash` class template for each cv-unqualified arithmetic type except for the extended integer types. This header also provides a definition for a partial specialization of the `hash` class template for any pointer type. The requirements for the members of these specializations are given in sub-clause 20.14.19 [unord.hash].

5. Change 20.17.4 [type.index.hash] p1 as indicated:

   >     template <> struct hash<type_index>;

   > > -1- Requires: the template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash])The header `<typeindex>` provides a definition for a specialization of the template `hash<type_index>`. The requirements for the members of this specialization are given in sub-clause 20.14.19 [unord.hash]. For an object `index` of type `type_index`, `hash<type_index>()(index)` shall evaluate to the same result as `index.hash_code()`.

6. Change 21.3.6 [basic.string.hash] p1 as indicated:

   >     template <> struct hash<string>;
   >     template <> struct hash<u16string>;
   >     template <> struct hash<u32string>;
   >     template <> struct hash<wstring>;

   > > -1- Requires: the template specializations shall meet the requirements of class template `hash` (20.14.19 [unord.hash])The header `<string>` provides definitions for specializations of the `hash` class template for the types `string`, `u16string`, `u32string`, and `wstring`. The requirements for the members of these specializations are given in sub-clause 20.14.19 [unord.hash].

7. Change 22.3.12 [vector.bool] p7 as indicated:

   >     template <class Allocator> struct hash<vector<bool, Allocator> >;

   > > -7- Requires: the template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash])The header `<vector>` provides a definition for a partial specialization of the `hash` class template for specializations of class template `vector<bool, Allocator>`. The requirements for the members of instantiations of this specialization are given in sub-clause 20.14.19 [unord.hash].

8. Change 32.4.3.2 [thread.thread.id] p14 as indicated:

   >     template <> struct hash<thread::id>;

   > > -14- Requires: the template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash])The header `<thread>` provides a definition for a specialization of the template `hash<thread::id>`. The requirements for the members of this specialization are given in sub-clause 20.14.19 [unord.hash].

]

[2012, Portland: Move to Tentatively Ready]

No further wording issues, so move to Tentatively Ready (post meeting issues processing).

[2013-04-20 Bristol]

Proposed resolution:

1. Change 19.5.7 [syserr.hash] as indicated:

   >     template <> struct hash<error_code>;

   > > -1- Requires: t The template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash].

2. Change 20.9.3 [bitset.hash] as indicated:

   >     template <size_t N> struct hash<bitset<N> >;

   > > -1- Requires: t The template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash]).

3. Change 20.11.7 [util.smartptr.hash] as indicated:

   >     template <class T, class D> struct hash<unique_ptr<T, D> >;

   > > -1- Requires: t The template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash]). For an object `p` of type `UP`, where `UP` is `unique_ptr<T, D>`, `hash<UP>()(p)` shall evaluate to the same value as `hash<typename UP::pointer>()(p.get())`. The specialization `hash<typename UP::pointer>` shall be well-formed.

   > > -?- Requires: The specialization `hash<typename UP::pointer>` shall be well-formed and well-defined, and shall meet the requirements of class template `hash` (20.14.19 [unord.hash]).

   >     template <class T> struct hash<shared_ptr<T> >;

   > > -2- Requires: t The template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash]). For an object `p` of type `shared_ptr<T>`, `hash<shared_ptr<T> >()(p)` shall evaluate to the same value as `hash<T*>()(p.get())`.

4. Change 20.14.19 [unord.hash] p2 as indicated: [Comment: For unknown reasons the extended integer types are not mentioned here, which looks like an oversight to me and makes also the wording more complicated. See 2119 for this part of the problem. — end comment]

   >     template <> struct hash<bool>;
   >     template <> struct hash<char>;
   >     […]
   >     template <> struct hash<long double>;
   >     template <class T> struct hash<T*>;

   > > -2- Requires: t The template specializations shall meet the requirements of class template `hash` (20.14.19 [unord.hash]).

5. Change 20.17.4 [type.index.hash] p1 as indicated:

   >     template <> struct hash<type_index>;

   > > -1- Requires: t The template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash]). For an object `index` of type `type_index`, `hash<type_index>()(index)` shall evaluate to the same result as `index.hash_code()`.

6. Change 21.3.6 [basic.string.hash] p1 as indicated:

   >     template <> struct hash<string>;
   >     template <> struct hash<u16string>;
   >     template <> struct hash<u32string>;
   >     template <> struct hash<wstring>;

   > > -1- Requires: t The template specializations shall meet the requirements of class template `hash` (20.14.19 [unord.hash]).

7. Change 22.3.12 [vector.bool] p7 as indicated:

   >     template <class Allocator> struct hash<vector<bool, Allocator> >;

   > > -7- Requires: t The template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash]).

8. Change 32.4.3.2 [thread.thread.id] p14 as indicated:

   >     template <> struct hash<thread::id>;

   > > -14- Requires: t The template specialization shall meet the requirements of class template `hash` (20.14.19 [unord.hash]).