I have a std::unique_ptr<Derived>
that I want to add to a std::vector<std::unique_ptr<Base>>
.
std::unique_ptr<Derived> derivedObject;
std::vector<std::unique_ptr<Base>> vec;
vec.push_back(derivedObject) // Invalid arguments
I have a std::unique_ptr<Derived>
that I want to add to a std::vector<std::unique_ptr<Base>>
.
std::unique_ptr<Derived> derivedObject;
std::vector<std::unique_ptr<Base>> vec;
vec.push_back(derivedObject) // Invalid arguments
unique_ptr guarantees that it's only one pointer that points to the memory, so you can't just copy it to the vector, you need to move it:
vec.push_back(std::move(derivedObject));
If you look at the unique_ptr constructors (http://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr) you see, that this class doesn't implement the copy constructor, but implements move constructor (http://en.cppreference.com/w/cpp/language/move_constructor).
This is because you cannot copy a std::unique_ptr
. The problem is solvable using std::move()
:
#include <iostream>
#include <memory>
#include <vector>
struct Base {
};
struct Derived : public Base {
};
int main()
{
std::unique_ptr<Derived> derivedObject;
std::vector<std::unique_ptr<Base>> vec;
vec.push_back(std::move(derivedObject));
// ^^^^^^^^^^ ^
}
Here's a live demo.
If T is a derived class of some base B, then std::unique_ptr < T > is implicitly convertible to std::unique_ptr < B >.
So, the problem is not of conversion failure.
The class satisfies the requirements of MoveConstructible and MoveAssignable, but not the requirements of either CopyConstructible or CopyAssignable.
This is what causes the failure. unique_ptr
can be moved but can't be copied, as that would break the single-ownership agreement.
So either use std::move
, or use make_derived directly:
vec.push_back(std::move(derivedObject)); //Option 1. When unique_ptr is already created.
OR,
vec.push_back(make_unique<Derived>()); //Option 2. New unique_ptr
Using option #2, you can avoid having a local variable for no purpose. Anyway upon performing move
on unique_ptr
, the object owned by the unique_ptr
is disposed. Demo.