根据C ++ 03 Standard(23.1 / 3),只有 copy-constructible 类对象可以存储在STL容器中。 可复制构造在20.1.3中描述,并要求“&”产生对象的地址。
现在假设我有这个课程:
class Class {
public:
Class* operator&()
{
//do some logging
return this;
}
const Class* operator&() const
{
//do some logging
return this;
}
//whatever else - assume it doesn't violate requierements
};
此类对象可以合法存储在STL容器中吗?
答案 0 :(得分:5)
是。在C ++ 03中,给定&
类型t
和T
类型u
的{{1}}的CopyConstructible要求为:
const T
的类型为&t
,地址为T*
,t
的类型为&u
,并提供const T*
的地址。您的重载运算符有此行为;因此,假设该类符合其他CopyConstructible和Assignable要求,则此类型的值可以存储在任何C ++ 03容器中。
C ++ 11放宽了这些要求,要求这些类型只能在具有这些要求的容器或操作中移动或复制,并删除u
必须做的相当奇怪的规范;所以你的课程仍然很好,再次假设它满足你使用的特定容器和操作集的所有其他要求。
答案 1 :(得分:1)
虽然在C ++ 03中我们只有 有可能复制构造/复制分配对象,但我们还有两个额外的,更强大的工具来构造对象和一个额外的工具来分配对象:移动建筑和任务和安置施工(基于完美的转发)。
由于这个原因,该标准为容器的value_type
提供了更多的回旋余地。例如,只要您不使用任何需要 CopyConstructible 的操作,您就可以在unique_ptr
中存储std::vector
s(仅限移动), CopyInsertable 或 CopyAssignable (例如将一个容器分配给另一个容器)。
此类对象可以合法存储在STL容器中吗?
是,无 可能在使用某个value_type
实例化的容器中使用的要求甚至提及地址-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
与< strong>T
并且给出m
类型的左值A
,指针 {{1p
类型的,T*
类型的表达式v
,以及T
类型的右值rv
,定义了以下术语。 (如果T
不支持分配器,则下面的术语定义为X
A
强>。)
std::allocator<T>
将 CopyInsertable复制到T
表示以下表达式格式正确:X
allocator_traits<A>::construct(m, p, v);
MoveInsertable进入T
表示以下表达式格式正确:X
allocator_traits<A>::construct(m, p, rv);
EmplaceConstructibleT
<来自X
< / em>,对于零个或多个参数args
,表示以下表达式格式正确:args
序列容器表的摘录(其中allocator_traits<A>::construct(m, p, args);
是有效的const迭代器,p
是t
类型的左值):
之前插入t的副本
T
要求:a.insert(p,t)
应为CopyInsertable为T
。对于X
和vector
,deque
也应为CopyAssignable。
效果:在p。
如果您从未使用该特定T
变体(以及需要CopyInsertible的其他成员),则您的类型不需要是CopyInsertable。很简单。所有其他成员也一样。 必须必须满足的 要求是可破坏的要求(逻辑,不是吗?)。