This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Open status.

### 2158. Conditional copy/move in `std::vector`

Section: 24.3.11.3 [vector.capacity] Status: Open Submitter: Nikolay Ivchenkov Opened: 2012-05-08 Last modified: 2022-11-06

Priority: 3

View other active issues in [vector.capacity].

View all other issues in [vector.capacity].

View all issues with Open status.

Discussion:

There are various operations on `std::vector` that can cause elements of the vector to be moved from one location to another. A move operation can use either rvalue or const lvalue as argument; the choice depends on the value of `!is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value`, where `T` is the element type. Thus, some operations on `std::vector` (e.g. 'resize' with single parameter, 'reserve', 'emplace_back') should have conditional requirements. For example, let's consider the requirement for 'reserve' in N3376 – 24.3.11.3 [vector.capacity]/2:

> Requires: `T` shall be `MoveInsertable` into `*this`.

This requirement is not sufficient if an implementation is free to select copy constructor when `!is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value` evaluates to true. Unfortunately, `is_copy_constructible` cannot reliably determine whether `T` is really copy-constructible. A class may contain public non-deleted copy constructor whose definition does not exist or cannot be instantiated successfully (e.g., `std::vector<std::unique_ptr<int>>` has copy constructor, but this type is not copy-constructible). Thus, the actual requirements should be:

- if `!is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value` then `T` shall be `CopyInsertable` into `*this`;

- otherwise `T` shall be `MoveInsertable` into `*this`.

Maybe it would be useful to introduce a new name for such conditional requirement (in addition to "`CopyInsertable`" and "`MoveInsertable`").

[2016-08 Chicago]

The problem does not appear to be as severe as described. The `MoveInsertable` requirements are consistently correct, but an issue may arise on the exception-safety guarantees when we check for `is_copy_constructible_v<T>`. The problem, as described, is typically for templates that appear to have a copy constructor, but one that fails to compile once instantiated, and so gives a misleading result for the trait.

In general, users should not provide such types, and the standard would not serve users well by trying to address support for such types. However, the standard should not be providing such types either, such as `vector<unique_ptr<T>>`. A possible resolution would be to tighten the constraints in Table 80 — Container Requirements, so that if the Requirements for the copy constructor/assingment operator of a container are not satisfied, that operation shall be deleted.

A futher problem highlighted by this approach is that there are no constraints on the copy-assignment operator, so that `vector<unique_ptr<T>>` should be `CopyAssignable`! However, we can lift the equivalent constraints from the Allocator-aware container requirements.

[08-2016, Chicago]

Fri PM: Move to Open

[2017-11 Albuquerque Saturday issues processing]

There's a bunch of uses of "shall" here that are incorrect. Also, CopyInsertable contains some semantic requirements, which can't be checked at compile time, so 'ill-formed' is not possible for detecting that.

[2018-06 Rapperswil Wednesday issues processing]

Daniel to provide updated wording.

[2018-06-12, Daniel provides revised wording]

Previous resolution [SUPERSEDED]:

> This wording is relative to N4606.

> 24.2.2.1 [container.requirements.general] Table 80 — Container requirements
> Expression | Return type | Operational semantics | Assertion/note/pre-/post-condition | Complexity
> `X(a)` |  |  | Requires: `T` is `CopyInsertable` into `X` (see below)., otherwise this expression shall be ill-formed. post: `a == X(a)`. | linear
> `X u(a)` `X u = a;` |  |  | Requires: `T` is `CopyInsertable` into `X` (see below)., otherwise this expression shall be ill-formed. post: `u == a`. | linear
> ... | ... | ... | ... | ...
> `r = a` | `X&` |  | Requires: `T` is `CopyInsertable` into `X` and `CopyAssignable`, otherwise this expression shall be ill-formed. post: `r == a`. | linear

> 24.2.2.1 [container.requirements.general] Table 83 — Allocator-aware container requirements
> Expression | Return type | Operational semantics | Assertion/note/pre-/post-condition | Complexity
> `a = t` | `X&` |  | Requires: `T` is `CopyInsertable` into `X` and `CopyAssignable`., otherwise this expression shall be ill-formed post: `r == a`. | linear

[2018-08-23 Batavia Issues processing. Priority to 3]

Changed `CopyInsertable` -> `Cpp17CopyInsertable` in the resolution.

Tim says that the wording is not quite right — it imposes additional requirements.

[2022-11-06; Daniel comments]

This issue has considerable overlap with LWG 3758.

Proposed resolution:

This wording is relative to N4750.

> The revised wording below uses the new Mandates: element introduced by adopting P0788R3 at the Rapperswil meeting 2018 and which will become a new term of art with Jonathan's omnibus paper throughout the Standard Library.

24.2.2.1 [container.requirements.general] Table 77 — Container requirements
Expression | Return type | Operational semantics | Assertion/note/pre-/post-condition | Complexity
`X(a)` |  |  | Mandates: Syntactic requirements of `T` is `Cpp17CopyInsertable` into `X` (see below). Requires: `T` is `Cpp17CopyInsertable` into `X` (see below). post: `a == X(a)`. | linear
`X u(a)` `X u = a;` |  |  | Mandates: Syntactic requirements of `T` is `Cpp17CopyInsertable` into `X` (see below). Requires: `T` is `Cpp17CopyInsertable` into `X` (see below). post: `u == a`. | linear
... | ... | ... | ... | ...
`r = a` | `X&` |  | Mandates: Syntactic requirements of `T` is `Cpp17CopyInsertable` into `X` (see below) and `CopyAssignable`. Requires: `T` is `Cpp17CopyInsertable` into `X` and `CopyAssignable`. post: `r == a`. | linear

24.2.2.1 [container.requirements.general] Table 80 — Allocator-aware container requirements
Expression | Return type | Operational semantics | Assertion/note/pre-/post-condition | Complexity
`a = t` | `X&` |  | Mandates: Syntactic requirements of `T` is `Cpp17CopyInsertable` into `X` and `CopyAssignable`. Requires: `T` is `Cpp17CopyInsertable` into `X` and `CopyAssignable`. post: `r == a`. | linear