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.

### 1332. Let Hash objects throw!

Section: 16.4.4.5 [hash.requirements] Status: C++11 Submitter: Daniel Krügler Opened: 2010-03-26 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [hash.requirements].

View all issues with C++11 status.

Discussion:

The currently added `Hash` requirements demand in Table 40 — `Hash` requirements [hash]:

> Table 40 — Hash requirements [hash]
> Expression | Return type | Requirement
> --- | --- | ---
> `h(k)` | `size_t` | Shall not throw exceptions. [..]

While it surely is a generally accepted idea that hash function objects should not throw exceptions, this basic constraint for such a fundamental requirement set does neither match the current library policy nor real world cases:

1. There are little known situations where a swap or move operation may throw an exception and in some popular domains such functions are required not to throw. But the library invested already efforts for good reasons to require "working" container implementations in the presence of throwing move or swap operations, see e.g. 22.2.6.2 [associative.reqmts.except], 22.2.7.2 [unord.req.except].
2. The container library is already specified to cope with potentially throwing comparers, predicates, and hash function objects, see above.

3. The new definition goes beyond the original hash requirements as specified by SGI library in regard to the exception requirement:

   > http://www.sgi.com/tech/stl/HashFunction.html

4. There are indeed real-world examples of potentially throwing hash functions, typically when the proxy pattern is used and when the to-be hashed proxied instance is some volatile object, e.g. a file or internet resource, that might suddenly be unavailable at the time of hashing.
5. With the new `noexcept` language facility libraries can still take advantage of no-throw guarantees of hasher functions with stricter guarantees.

Even though the majority of all known move, swap, and hash functions won't throw and in some cases must not throw, it seems like unnecessary over-constraining the definition of a Hash functor not to propagate exceptions in any case and it contradicts the general principle of C++ to impose such a requirement for this kind of fundamental requirement.

[ 2010-11-11 Daniel asks the working group whether they would prefer a replacement for the second bullet of the proposed resolution (a result of discussing this with Alberto) of the form: ]

Add to 20.14.19 [unord.hash]/1 a new bullet:

> 1 The unordered associative containers defined in Clause 23.5 use specializations of the class template `hash` as the default hash function. For all object types `Key` for which there exists a specialization `hash<Key>`, the instantiation `hash<Key>` shall:

> - satisfy the `Hash` requirements (20.2.4), with `Key` as the function call argument type, the `DefaultConstructible` requirements (33), the `CopyAssignable` requirements (37),
> - be swappable (20.2.2) for lvalues,
> - provide two nested types `result_type` and `argument_type` which shall be synonyms for `size_t` and `Key`, respectively,
> - satisfy the requirement that if `k1 == k2` is true, `h(k1) == h(k2)` is also true, where `h` is an object of type `hash<Key>` and `k1` and `k2` are objects of type `Key`,.
> - satisfy the requirement `noexcept(h(k)) == true`, where `h` is an object of type `hash<Key>` and `k` is an object of type `Key`, unless `hash<Key>` is a user-defined specialization that depends on at least one user-defined type.

[Batavia: Closed as NAD Future, then reopened. See the wiki for Tuesday.]

Proposed resolution:

1. Change Table 26 — `Hash` requirements [tab:hash] as indicated:

   > Table 26 — `Hash` requirements [tab:hash]
   > Expression | Return type | Requirement
   > --- | --- | ---
   > `h(k)` | `size_t` | Shall not throw exceptions. […]

2. Add to 20.14.19 [unord.hash] p. 1 a new bullet:

   > 1 The unordered associative containers defined in Clause 22.5 [unord] use specializations of the class template `hash` as the default hash function. For all object types `Key` for which there exists a specialization `hash<Key>`, the instantiation `hash<Key>` shall:

   > - satisfy the `Hash` requirements ([hash.requirements]), with `Key` as the function call argument type, the `DefaultConstructible` requirements (Table [defaultconstructible]), the `CopyAssignable` requirements (Table [copyassignable]),
   > - be swappable ([swappable.requirements]) for lvalues,
   > - provide two nested types `result_type` and `argument_type` which shall be synonyms for `size_t` and `Key`, respectively,
   > - satisfy the requirement that if `k1 == k2` is true, `h(k1) == h(k2)` is also true, where `h` is an object of type `hash<Key>` and `k1` and `k2` are objects of type `Key`,.
   > - satisfy the requirement that the expression `h(k)`, where `h` is an object of type `hash<Key>` and `k` is an object of type `Key`, shall not throw an exception, unless `hash<Key>` is a user-defined specialization that depends on at least one user-defined type.