存储具有重载“运算符&”的类的对象在STL容器合法的C ++?

时间:2011-12-28 10:26:48

标签: c++ stl operator-overloading

根据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容器中吗?

2 个答案:

答案 0 :(得分:5)

是。在C ++ 03中,给定&类型tT类型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 ,指针 {{1 p 类型的 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); EmplaceConstructible T <来自 X < / em>,对于零个或多个参数 args ,表示以下表达式格式正确:       args

  •   

序列容器表的摘录(其中allocator_traits<A>::construct(m, p, args);是有效的const迭代器,pt类型的左值):

  

T
  要求: a.insert(p,t) 应为CopyInsertable为 T 。对于 X vector deque 也应为CopyAssignable。
  效果:在p。

之前插入t的副本

如果您从未使用该特定T变体(以及需要CopyInsertible的其他成员),则您的类型不需要是CopyInsertable。很简单。所有其他成员也一样。 必须必须满足的 要求是可破坏的要求(逻辑,不是吗?)。