Wesley Richmond
Wesley Richmond

Reputation: 11

Can't push_back an object with a unique_ptr to a std::vector

I am trying to create an Entity which can hold a pointer to its parent and a vector to its children.

The problem is when I try to emplace_back or push_back to the vector of children, I get

Error C2280 'Entity::Entity(const Entity &)': attempting to reference a deleted function

Due to the fact I have a unique_ptr in the Entity.

I thought that adding a move-constructor would solve this problem but it has not.

I have included a minimal verifiable runnable example here below.

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

struct Entity
{
   //////// data
   unique_ptr<Entity> mParent;
   std::vector<Entity> mChildren;

   //////// ctors
   // default
   Entity() = default;
   // move
   Entity(Entity && entity): mParent{std::move(entity.mParent)}{}

   //////// functions
   void add_child(Entity const && entity)
   {
       mChildren.emplace_back(entity); // COMMENT OUT THIS LINE FOR FUNCTIONAL CODE
       //Error  C2280 'Entity::Entity(const Entity &)': attempting to reference a deleted function in... include\xmemory0 881
   };
};

int main()
{
   Entity entity;
   entity.add_child(Entity());
   return 0;
}

Upvotes: 1

Views: 817

Answers (1)

pts
pts

Reputation: 87311

Drop the const:

void add_child(Entity && entity)

, and use:

mChildren.push_back(std::move(entity));

Applying these 2 changes above made it compile for me.

Explanation: You want to call void push_back( T&& value ); (or similarly with emplace_back) in vector<T>, where T is Entity. The other overload is void push_back( const T& value );, which doesn't compile, because its implementation (method body) attempts to call the copy constructor of T, and Entity doesn't have a copy constructor. The implementation void push_back( T&& value ); calls the move constructor of T, and Entity has a move constructor, so it compiles.

To make sure that void push_back( T&& value ); is called, you want to pass an Entity&& to push_back. For that you need both changes above. Without either, entity can't be converted to Entity&&.

See also https://en.cppreference.com/w/cpp/container/vector/push_back.

Upvotes: 2

Related Questions