Reputation: 4523
Given this class with a unique_ptr:
class MyClass
{
public:
MyClass(){}
MyClass(MyClass &&other) : ptr(std::move(other.ptr)){}
std::unique_ptr <int> ptr;
};
Is there any way to make it possible to have a std::vector<MyClass>
?
void ThisBreaksIt()
{
MyClass instance;
std::vector<MyClass> mv;
mv.push_back(instance);
}
As-is, this gives me the error
error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
This makes sense, since I have no copy constrctor, and when the compiler tries creating a default copy constructor, it tries copying the unique_ptr
, which isn't allowed.
I can make it compile by adding this constructor:
MyClass(const MyClass&){}
But of course, this leaves the unique_ptr
uninitialized, and is not what I want.
I can't add
MyClass(const MyClass& other) : ptr(std::move(other.ptr)){}
because it's const
, and I cant call std::move() on a const
object. I can create the constructor
MyClass(MyClass& other) : ptr(std::move(other.ptr)){}
but doesn't solve the original compile error, as vector::push_back
uses a const
copy constructor.
So, I'm stuck. Is there a way to do what I'm trying to do?
All of these issues go away if I just use a shared_ptr
instead of unique_ptr
. Is that what I should be doing?
Upvotes: 2
Views: 158
Reputation: 254431
There's no problem storing a non-copyable type in a vector; it's only required to be movable, as yours is.
The problem is that this:
mv.push_back(instance);
tries to insert a copy of instance
, and the class is not copyable. But it is movable:
mv.push_back(std::move(instance));
Note that there's no need to write your own default and move constructors in this example. The implicit ones will do the exactly what yours do.
Upvotes: 6
Reputation: 4076
You can use emplace_back. This only allows adding rvalues.
Therefore do this:
void ThisShouldFixIt()
{
mv.emplace_back(MyClass());
}
Note that emplace_back can call the applicable constructor of T implace, as mentioned below. For what you are doing push_back is fine though, given that a version taking an rvalue reference does exist.
Upvotes: 0