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

### 1182. Unfortunate hash dependencies

Section: 20.14.19 [unord.hash] Status: C++11 Submitter: Alisdair Meredith Opened: 2009-07-28 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [unord.hash].

View all issues with C++11 status.

Discussion:

Addresses UK 324

The implied library dependencies created by spelling out all the `hash` template specializations in the `<functional>` synopsis are unfortunate. The potential coupling is greatly reduced if the `hash` specialization is declared in the appropriate header for each library type, as it is much simpler to forward declare the primary template and provide a single specialization than it is to implement a `hash` function for a `string` or `vector` without providing a definition for the whole `string/vector` template in order to access the necessary bits.

Note that the proposed resolution purely involves moving the declarations of a few specializations, it specifically does not make any changes to 20.14.19 [unord.hash].

[ 2009-09-15 Daniel adds: ]

I suggest to add to the current existing proposed resolution the following items.

- Add to the very first strike-list of the currently suggested resolution the following lines:

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

- Add the following declarations to 19.5 [syserr], header `<system_error>` synopsis after // 19.5.4:

  >     // 19.5.x hash support
  >     template <class T> struct hash;
  >     template <> struct hash<error_code>;

- Add a new clause 19.5.X (probably after 19.5.4):

  > 19.5.X Hash support [syserr.hash]

  >     template <> struct hash<error_code>;

  > > An explicit specialization of the class template hash (20.14.19 [unord.hash]) shall be provided for the type `error_code` suitable for using this type as key in unordered associative containers (22.5 [unord]).

- Add the following declarations to 32.4.3.2 [thread.thread.id] just after the declaration of the comparison operators:

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

- Add a new paragraph at the end of 32.4.3.2 [thread.thread.id]:

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

  > > An explicit specialization of the class template hash (20.14.19 [unord.hash]) shall be provided for the type `thread::id` suitable for using this type as key in unordered associative containers (22.5 [unord]).

- Issue 889 independently suggests moving the specialization `std::hash<std::thread::id>` to header `<thread>`.

[ 2009-11-13 Alisdair adopts Daniel's suggestion and the extended note from 889. ]

[ 2010-01-31 Alisdair: related to 1245 and 978. ]

[ 2010-02-07 Proposed wording updated by Beman, Daniel, Alisdair and Ganesh. ]

[ 2010-02-09 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]

Proposed resolution:

Strike the following specializations declared in the `<functional>` synopsis p2 20.14 [function.objects]

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

>     template <> struct hash<std::error_code>;
>     template <> struct hash<std::thread::id>;
>     template <class Allocator> struct hash<std::vector<bool, Allocator> >;
>     template <std::size_t N> struct hash<std::bitset<N> >;

Add the following at the end of 20.14.19 [unord.hash]:

>     template <> struct hash<bool>;
>     template <> struct hash<char>;
>     template <> struct hash<signed char>;
>     template <> struct hash<unsigned char>;
>     template <> struct hash<char16_t>;
>     template <> struct hash<char32_t>;
>     template <> struct hash<wchar_t>;
>     template <> struct hash<short>;
>     template <> struct hash<unsigned short>;
>     template <> struct hash<int>;
>     template <> struct hash<unsigned int>;
>     template <> struct hash<long>;
>     template <> struct hash<long long>;
>     template <> struct hash<unsigned long>;
>     template <> struct hash<unsigned long long>;
>     template <> struct hash<float>;
>     template <> struct hash<double>;
>     template <> struct hash<long double>;
>     template<class T> struct hash<T*>;

> Specializations meeting the requirements of class template `hash` 20.14.19 [unord.hash].

Add the following declarations to 19.5 [syserr], header `<system_error>` synopsis after // 19.5.4:

>     // [syserr.hash] hash support
>     template <class T> struct hash;
>     template <> struct hash<error_code>;

Add a new clause 19.5.X (probably after 19.5.4):

> 19.5.X Hash support [syserr.hash]

>     template <> struct hash<error_code>;

> Specialization meeting the requirements of class template `hash` 20.14.19 [unord.hash].

Add the following declarations to the synopsis of `<string>` in 21.3 [string.classes]

>     // [basic.string.hash] hash support
>     template <class T> struct hash;
>     template <> struct hash<string>;
>     template <> struct hash<u16string>;
>     template <> struct hash<u32string>;
>     template <> struct hash<wstring>;

Add a new clause 21.4.X

> 21.4.X Hash support [basic.string.hash]>

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

> Specializations meeting the requirements of class template `hash` 20.14.19 [unord.hash].

Add the following declarations to the synopsis of `<vector>` in 22.3 [sequences]

>     // 21.4.x hash support
>     template <class T> struct hash;
>     template <class Allocator> struct hash<vector<bool, Allocator>>;

Add a new paragraph to the end of 22.3.12 [vector.bool]

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

> Specialization meeting the requirements of class template `hash` 20.14.19 [unord.hash].

Add the following declarations to the synopsis of `<bitset>` in 20.9.2 [template.bitset]

>     // [bitset.hash] hash support
>     template <class T> struct hash;
>     template <size_t N> struct hash<bitset<N> >;

Add a new subclause 20.3.7.X [bitset.hash]

> 20.3.7.X bitset hash support [bitset.hash]

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

> Specialization meeting the requirements of class template `hash` 20.14.19 [unord.hash].

Add the following declarations to 32.4.3.2 [thread.thread.id] synopsis just after the declaration of the comparison operators:

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

Add a new paragraph at the end of 32.4.3.2 [thread.thread.id]:

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

> Specialization meeting the requirements of class template `hash` 20.14.19 [unord.hash].

Change Header <typeindex> synopsis 20.17.1 [type.index.synopsis] as indicated:

>     namespace std {
>     class type_index;
>       // [type.index.hash] hash support
>       template <class T> struct hash;
>       template<> struct hash<type_index>;  : public unary_function<type_index, size_t> {
>         size_t operator()(type_index index) const;
>       }
>     }

Change Template specialization hash<type_index> [type.index.templ] as indicated:

> 20.11.4 Template specialization hash<type_index> [type.index.templ] Hash support [type.index.hash]

>     size_t operator()(type_index index) const;

> > Returns: `index.hash_code()`

>     template<> struct hash<type_index>;

> Specialization meeting the requirements of class template `hash` [unord.hash]. For an object `index` of type `type_index`, `hash<type_index>()(index)` shall evaluate to the same value as `index.hash_code()`.