虽然在 C++03 中我们只有可以复制构造/复制分配对象,但我们获得了两个额外的、迄今为止更强大的工具来构造对象和一个额外的工具来分配对象: move 构造和 assignment 和 emplace 构造(基于完美转发)。
多亏了这一点,该标准为容器方式的value_type 提供了更多的要求余地。例如,您可以将只能移动的unique_ptrs 存储在std::vector 中,只要您不使用任何需要CopyConstructible、CopyInsertable 的操作 或 CopyAssignable(例如将一个容器分配给另一个)。
这个类对象可以合法存储在 STL 容器中吗?
是,没有要求可以用在某个value_type实例化的容器中,甚至提到address-of以任何方式操作。
§17.6.3.1 [utility.arg.requirements]
C++ 标准库中的模板定义引用了各种命名需求,其详细信息在表 17-24 中列出。
(表 17 和 18 是可比要求)
Table 19 — DefaultConstructible requirements [defaultconstructible]
Expression Post-condition
T t; object t is default-initialized
T u{}; object u is value-initialized
T() a temporary object of type T is value-initialized
T{}
Table 20 — MoveConstructible requirements [moveconstructible]
Expression Post-condition
T u = rv; u is equivalent to the value of rv before the construction
T(rv) T(rv) is equivalent to the value of rv before the construction
rv’s state is unspecified
Table 21 — CopyConstructible requirements (in addition to MoveConstructible) [copyconstructible]
Expression Post-condition
T u = v; the value of v is unchanged and is equivalent to u
T(v) the value of v is unchanged and is equivalent to T(v)
Table 22 — MoveAssignable requirements [moveassignable]
Expression Return type Return value Post-condition
t = rv T& t t is equivalent to the value of
rv before the assignment
rv’s state is unspecified.
Table 23 — CopyAssignable requirements(in addition to MoveAssignable) [copyassignable]
Expression Return type Return value Post-condition
t = v T& t t is equivalent to v, the value of
v is unchanged
Table 24 — Destructible requirements [destructible]
Expression Post-condition
u.~T() All resources owned by u are reclaimed, no exception is propagated.
然后我们自己也得到了容器需求。这些基于它们的分配器类型:
§23.2.1 [container.requirements.general] p13
除数组外,本条款和 (21.4) 中定义的所有容器都满足分配器感知容器的附加要求,如表 99 中所述。
给定一个容器类型 X,其 allocator_type 与 A 相同,value_type 与 T 并给定一个 A 类型的左值 m,一个 T* 类型的指针 p ,一个 T 类型的表达式 v,以及一个 @987654339 类型的右值 rv @,定义了以下术语。 (如果 X 不能识别分配器,则下面的术语定义为好像 A 是 std::allocator<T>。) p>
T is CopyInsertable into X 表示以下表达式是格式正确的:
allocator_traits<A>::construct(m, p, v);
T 是 MoveInsertable into X 表示以下表达式格式正确:
allocator_traits<A>::construct(m, p, rv);
T 是 EmplaceConstructible 到 X 从 args,为零或多个参数args,表示以下表达式格式正确:
allocator_traits<A>::construct(m, p, args);
序列容器表的摘录(其中p 是有效的常量迭代器,t 是T 类型的左值):
a.insert(p,t)
要求: T 应可复制插入到 X。对于 vector 和 deque,T 也应是 CopyAssignable。
效果:在 p 之前插入 t 的副本。
如果您从不使用特定的 insert 变体(以及其他需要 CopyInsertible 的成员),则您的类型不需要是 CopyInsertable。就这么简单。所有其他成员也是如此。 必须满足的唯一要求是 Destructible 要求(合乎逻辑,不是吗?)。