Because the requirements say so:
count returns the number of elements matching a specific key, and key comparisons are evaluated off of an object of type
X::key_type for any unordered associative container type
std::unordered_maps are such containers)
n3337 23.2.5/5 [unord.req]
Keyare considered equivalent if the container’s key equality predicate returns
truewhen passed those values. ... For any two keys
k2in the same container, calling
pred(k1, k2)shall always return the same value. ...
For an unordered map,
X::key_type is defined as part of its template parameter list:
template< class Key, // ^^^ member type key_type set from this parameter class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>, // ^^^^^^^^ member type key_equal set from this parameter class Allocator = std::allocator< std::pair<const Key, T> > > class unordered_map;
The only constraints I can find on
key_type also applies to
n3337 23.2.5/9 [unord.req]2
... the requirements placed on
value_typein Table 96 apply instead to
So we just need to know the requirements placed on
value_type in table 96, which specifies the requirements for a
Container. In the very first row, we have:
n3337, table 963
X is again the type of the Container, and
T is the type of objects it's storing.
Destructibleobjects are not allowed to have throwing destructors. That's their only requirement.
n3337, table 24
u.∼T()All resources owned by
uare reclaimed, no exception is propagated
u being an object of type
T which fulfills the requirements of
Thus, there is no restriction on the throw guarantees offered by the key comparison function for the
unordered_map, and so no guarantee on the
operator== operation provided from
std::equal_to to implement the required behavior. The key itself lacks any such restrictions, so: the comparison function is allowed to throw, and any function which uses the comparison function is also allowed to throw.
count needs to count the stored values with keys that match the supplied key with the comparison function, so it may throw.
clear may be
noexcept because the standard bans throwing in destructors:
In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.
In particular, the effects are undefined in the following cases:
- if any replacement function or handler function or destructor operation exits via an exception, unless specifically allowed in the applicable Required behavior: paragraph.
since the only client-dependent code
clear executes may not throw exceptions, and the implementation doesn't need to, it may be and has been marked
1. The n4140 standard draft (near c++14) does not appear to have changed this clause at all.
2. n4140 retains this phrasing, moved to clause 10 from clause 9.
Container requirements are also listed in Table 96 of n4140, and list the requirement for
T as being
Erasable, which also places no restrictions on
4. The wording of this clause hasn't changed in n4140.