Is storing class objects with an overloaded & operator in STL containers legal in C ++?

According to the C ++ 03 standard (23.1 / 3), only objects with the ability to copy can be stored in STL containers. The copied construct is described in 20.1.3 and requires that "&" give the address of the object.

Now suppose I have this class:

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 }; 

Is it possible to legally store class objects in STL containers?

+6
source share
2 answers

Yes. In C ++ 03, CopyConstructible requirements for & , given values โ€‹โ€‹of t type t and u type const T :

  • &t is of type T* and gives the address t and
  • &u is of type const T* and gives the address u .

Your overloaded statements have this behavior; therefore, assuming the class meets the other requirements of CopyConstructible and Assignable, values โ€‹โ€‹of this type can be stored in any C ++ 03 container.

C ++ 11 mitigates these requirements by requiring types to be moveable or copyable only in containers or operations that specifically have such requirements, and eliminate the rather odd specification of what & ; therefore, your class is still beautiful, again believing that it meets all the other requirements for a specific container and the many operations you use.

+5
source

While in C ++ 03 we had the opportunity to copy objects to create / copy, we get two additional, much more powerful tools for creating objects and one additional tool for assigning objects: move the structure and purpose and replace the structure ( based on perfect shipment).

Thanks to this, the standard gives the value_type container path more options in its requirements. For example, you are allowed to store unique_ptr s, which are just a move, in std::vector unless you use any operations that require CopyConstructible, CopyInsertable or CopyAssignable (e.g. assigning one container to another).

Is it possible to legally store class objects in STL containers?

Yes , none of the requirements that can be used in a container created with a specific value_type does not even mention the operator address in any way.

ยง17.6.3.1 [utility.arg.requirements]

Template definitions in the C ++ Standard Library refer to various named requirements, details of which are given in Tables 17-24.

(Tables 17 and 18 are comparable requirements)

 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& tt 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& tt 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. 

Then we also got the container requirements ourselves. They are based on valve types:

ยง23.2.1 [container.requirements.general] p13

All containers defined in this section and in (21.4), except for the array, satisfy the additional requirements of the container supporting the dispenser, as described in table 99. For the container type X with the identifier allocator_type identical to A and value_type identical to T and specify lvalue m type A , a pointer p type T* , an expression v type T , and rvalue rv type T , the following terms are defined. (If X not distributor aware, the terms below are defined as if A were std::allocator<T> .)

  • T - this is CopyInsertable in X means that the following expression is well-formed: allocator_traits<A>::construct(m, p, v);

  • T - MoveInsertable in X means that the following expression is well-formed: allocator_traits<A>::construct(m, p, rv);

  • T is EmplaceConstructible in X from args , for zero or more args arguments, means that the following expression is well-formed: allocator_traits<A>::construct(m, p, args);

Excerpt from the table for sequence containers (where p is a valid constant iterator and T is an lvalue of type T ):

a.insert(p,t)
Required: T must be CopyInsertable in X For vector and deque , T will also be CopyAssignable.
Effects: Inserts a copy of t before p.

If you never use this particular insert option (and other members that need CopyInsertible), your type does not have to be CopyInsertable. Easy. The same goes for all the other participants. The only requirement that must be met is the requirement of the Destroyed (logical, isn't it?).

+1
source

Source: https://habr.com/ru/post/904592/


All Articles