因为需求是这样说的:
count 返回匹配特定键的元素的数量,并且键比较是根据任何无序关联容器类型X 的X::key_type 类型的对象评估的(实例化的std::unordered_maps 就是这样的容器)
n3337 23.2.5/5 [unord.req]
如果容器的键相等谓词在传递这些值时返回 true,则认为 Key 类型的两个值 k1 和 k2 是等效的。 ...对于同一容器中的任意两个键k1 和k2,调用pred(k1, k2) 应始终返回相同的值。 ...
对于无序映射,X::key_type 被定义为其模板参数列表的一部分:
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;
我可以在key_type 上找到的唯一限制也适用于value_type:
n3337 23.2.5/9 [unord.req]2
...表 96 中对 value_type 的要求适用于 key_type 和 mapped_type。
所以我们只需要知道表 96 中对value_type 的要求,它指定了Container 的要求。在第一行,我们有:
n3337,表 963
X::value_type |返回T | 要求: T 是 Destructible
其中X 又是容器的类型,T 是它存储的对象的类型。 Destructibleobjects 不允许有抛出的析构函数。这是他们唯一的要求。
n3337,表 24
u.∼T()u拥有的所有资源都被回收,不传播异常
(u 是 T 类型的对象,满足 Destructible 的要求)
因此,对于unordered_map,键比较函数提供的抛出保证没有限制,因此std::equal_to提供的operator==操作不保证实现要求的行为。 key 本身没有这样的限制,所以:允许比较函数抛出,任何使用比较函数的函数也允许抛出。 count 需要用 key 计算存储的值将提供的键与比较函数匹配,因此它可能会抛出。
clear 可能是noexcept,因为标准禁止抛出析构函数:
17.6.4.8/1,24 [res.on.functions]
在某些情况下(替换函数、处理函数、对用于实例化标准库模板组件的类型的操作),C++ 标准库依赖于 C++ 程序提供的组件。如果这些组件不符合其要求,则标准不会对实施提出任何要求。
特别是在以下情况下效果是不确定的:
...
- 如果任何替换函数或处理函数或析构函数操作通过异常退出,除非在适用的必需行为:段落中明确允许。
...
由于唯一依赖于客户端的代码clear执行可能不会抛出异常,而实现也不需要,它可能并且已经被标记为noexcept
注意事项:
1. n4140 标准草案(接近 c++14)似乎根本没有改变这个条款。
2。 n4140 保留了这一措辞,从第 9 条移至第 10 条。
3。 Container的要求也列在n4140的表96中,将T的要求列为Erasable,这对operator==也没有限制
4。该条款的措辞在 n4140 中没有改变。