N4868 22.2.3 table 77 Sequence container requirements states that insert(iterator pos, size_type count, T value) requires T to be CopyInsertable and CopyAssignable in any sequence container. It means no moves or swaps can be made to shift elements if pos is already occupied.
The question is how does std::vector handle situations when it has enough space to insert n elements and it needs to shift elements pointed by pos? Does it always reallocate memory no matter on T? Or does it use copy constructor/assignment to shift elements and then assign them to required place? If so, does it shift only when T's copy construction/assignment does not throw?
If a type is CopyAssignable, it also must be MoveAssignable. Similarly for CopyInsertable, it must also be MoveInsertable.
See table 31 in [utility.arg.requirements]:
Cpp17CopyAssignable requirements (in addition to Cpp17MoveAssignable):
And [container.requirements.general]p(16.4):
Tis Cpp17CopyInsertable intoXmeans that, in addition toTbeing Cpp17MoveInsertable intoX, [...]
Even for a type which only declares a copy constructor, a move like T x = std::move(rv); would still work because it would select the copy constructor T::T(const T&).
So the misunderstanding in your question is here:
It means no moves or swaps can be made to shift elements if pos is already occupied.
Moves can be done. An algorithm would be (if there is enough space) move-insert into count elements after the end, then move_backwards the elements from [it, end()-count) to end(), then copy assign value to [it, it+count).
The requirement is not simply MoveInsertable because if you do insert(end(), count, value), the value must be copy inserted at the end, requiring it to be CopyInsertable. And the copy assignment is required to assign the value to existing objects in the previous case where the iterator is not at the end.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With