Consider the following program which inserts a range of elements into a vector:
vector<string> v1;
vector<string> v2;
v1.push_back("one");
v1.push_back("two");
v1.push_back("three");
v2.push_back("four");
v2.push_back("five");
v2.push_back("six");
v1.insert(v1.end(), v2.begin(), v2.end());
This efficiently copies the range, allocating enough space in the target vector for the entire range so that a maximum of one resize will be required. Now consider the following program which attempts to move a range into a vector:
vector<string> v1;
vector<string> v2;
v1.push_back("one");
v1.push_back("two");
v1.push_back("three");
v2.push_back("four");
v2.push_back("five");
v2.push_back("six");
for_each ( v2.begin(), v2.end(), [&v1]( string & s )
{
v1.emplace_back(std::move(s));
});
This performs a successful move but doesn’t enjoy the benefits that insert() has with regard to preallocating space in the target vector, so the vector could be resized several times during the operation.
So my question is, is there an insert equivalent which can move a range into a vector?
You use a
move_iteratorwithinsert:The example in 24.5.3 is almost exactly this.
You’ll get the optimization you want if (a)
vector::insertuses iterator-tag dispatch to detect the random-access iterator and precalculate the size (which you’ve assumed it does in your example that copies), and (b)move_iteratorpreserves the iterator category of the iterator it wraps (which is required by the standard).On an obscure point: I’m pretty sure that
vector::insertcan emplace from the source (which is irrelevant here, since the source is the same type as the destination, so an emplace is the same as a copy/move, but would be relevant to otherwise-identical examples). I haven’t yet found a statement that it’s required to do so, I’ve just inferred it from the fact that the requirement on the iterator pairi,jpassed toinsertis thatTbeEmplaceConstructiblefrom*i.