Reputation: 10868
I have two classes, say Base
and Derived: public Base
and two std::vector
s, one holding elements of type unique_ptr<Base>
and other one holds elements of type unique_ptr<Derived>
How can I transfer ownership of all elements from second vector into first one? I already tried:
vector<unique_ptr<Base>> v1;
vector<unique_ptr<Derived>> v2;
// do something
std::move(v2.begin(),v2.end(),v1.begin()); // This line crashed
v1 = std::move(v2); // And this gives a compiler error
Upvotes: 1
Views: 1716
Reputation: 218790
As I did not see this answer elsewhere, I wanted to remind everyone of the very simple member function assign
of vector
:
vector<unique_ptr<Base>> v1;
vector<unique_ptr<Derived>> v2;
// do something
v1.assign(make_move_iterator(v2.begin()), make_move_iterator(v2.end()));
Upvotes: 6
Reputation: 275435
template<class Dest, class Src>
void move_contents_to(Dest&dest, Src const& src)=delete;
template<class Dest, class Src>
void move_contents_to(Dest&dest, Src& src)=delete;
template<class Dest, class Src>
void move_contents_to(Dest&dest, Src&& src){
using std::begin; using std::end;
dest = Dest{std::make_move_iterator(begin(src)),std::make_move_iterator(end(src))};
}
the above will work for most std
containers, and will work with raw C style arrays on the right. For safety, I require the src
to be an rvalue reference, so which is being moved is clear.
Upvotes: 0
Reputation: 64308
You need to make sure v1
is the proper size before moving into it. For example:
#include <algorithm>
#include <vector>
#include <memory>
using std::vector;
using std::unique_ptr;
struct Base {
};
struct Derived : Base {
};
int main()
{
vector<unique_ptr<Base>> v1;
vector<unique_ptr<Derived>> v2;
v2.push_back(unique_ptr<Derived>(new Derived));
v2.push_back(unique_ptr<Derived>(new Derived));
v2.push_back(unique_ptr<Derived>(new Derived));
v1.resize(v2.size());
std::move(v2.begin(),v2.end(),v1.begin());
}
This is because the move algorithm doesn't change the size of the container itself. It is implemented like this (taken from http://en.cppreference.com/w/cpp/algorithm/move):
template<class InputIt, class OutputIt>
OutputIt move(InputIt first, InputIt last, OutputIt d_first)
{
while (first != last) {
*d_first++ = std::move(*first++);
}
return d_first;
}
Upvotes: 6
Reputation: 217358
You may use the following:
std::vector<std::unique_ptr<Base>> v1(v2.size());
std::copy(std::make_move_iterator(v2.begin()), std::make_move_iterator(v2.end()), v1.begin());
Upvotes: 0
Reputation: 3349
Do it elementwise.
for (auto&& elem : v2)
{
v1.push_back(std::move(elem));
}
Upvotes: 1