Search code examples
c++c++11vectormoveunique-ptr

Move vector<unique_ptr<Derived>> to a vector<unique_ptr<Base>>


I have two classes, say Base and Derived: public Base and two std::vectors, 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

Solution

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