2109. Incorrect requirements for hash specializations

Section: 22.5.6 [syserr.hash], 23.11.7 [util.smartptr.hash], 23.14.15 [unord.hash], 23.18.1 [type.index.synopsis], 24.3.5 [basic.string.hash], 26.3.12 [vector.bool], 33.3.2.1 [thread.thread.id] Status: C++14 Submitter: Daniel Krügler Opened: 2011-12-04 Last modified: 2016-02-10

Priority: Not Prioritized

View all issues with C++14 status.

Discussion:

23.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 22.5.6 [syserr.hash] as indicated:

    template <> struct hash<error_code>;
    

    -1- Requires: the template specialization shall meet the requirements of class template hash (23.14.15 [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 23.14.15 [unord.hash].

  2. Change 23.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 (23.14.15 [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 23.14.15 [unord.hash].

  3. Change 23.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 (23.14.15 [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 23.14.15 [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 (23.14.15 [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 (23.14.15 [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 23.14.15 [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 23.14.15 [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 (23.14.15 [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 23.14.15 [unord.hash].

  5. Change 23.18.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 (23.14.15 [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 23.14.15 [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 24.3.5 [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 (23.14.15 [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 23.14.15 [unord.hash].

  7. Change 26.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 (23.14.15 [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 23.14.15 [unord.hash].

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

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

    -14- Requires: the template specialization shall meet the requirements of class template hash (23.14.15 [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 23.14.15 [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 22.5.6 [syserr.hash] as indicated:

    template <> struct hash<error_code>;
    

    -1- Requires: tThe template specialization shall meet the requirements of class template hash (23.14.15 [unord.hash].

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

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

    -1- Requires: tThe template specialization shall meet the requirements of class template hash (23.14.15 [unord.hash]).

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

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

    -1- Requires: tThe template specialization shall meet the requirements of class template hash (23.14.15 [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 (23.14.15 [unord.hash]).

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

    -2- Requires: tThe template specialization shall meet the requirements of class template hash (23.14.15 [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 23.14.15 [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: tThe template specializations shall meet the requirements of class template hash (23.14.15 [unord.hash]).

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

    template <> struct hash<type_index>;
    

    -1- Requires: tThe template specialization shall meet the requirements of class template hash (23.14.15 [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 24.3.5 [basic.string.hash] p1 as indicated:

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

    -1- Requires: tThe template specializations shall meet the requirements of class template hash (23.14.15 [unord.hash]).

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

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

    -7- Requires: tThe template specialization shall meet the requirements of class template hash (23.14.15 [unord.hash]).

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

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

    -14- Requires: tThe template specialization shall meet the requirements of class template hash (23.14.15 [unord.hash]).