I have an Entity class with a private constructor and public CreateEntity function. CreateEntity heap-allocates new entities. In my app, I'd like to use a unique pointer to the returned entity. I found a solution with a temporary unique pointer and two move instructions. How do I write the two lines in Start() with make_unique and a single move instruction?
class Entity
{
public:
Entity(const Entity&) = delete;
Entity& operator=(const Entity&) = delete;
Entity(Entity&&) = default;
Entity& operator=(Entity&&) = default;
static Entity CreateEntity();
private:
Entity(id_t id): m_ID(id) {}
private:
uint32_t m_ID;
};
Entity Entity::CreateEntity()
{
static id_t currentID = 0;
return Entity{currentID };
}
struct Lucre : public Application
{
bool Start();
std::unique_ptr<Entity> m_Object;
}
bool Lucre::Start()
{
std::unique_ptr<Entity> ptr( new Entity(std::move(Entity::CreateEntity())));
m_Object = std::move(ptr);
}
CodePudding user response:
You can combine the 2 lines in Lucre::Start() like this:
m_CameraObject.reset( new Entity( Entity::CreateEntity() ) );
Here, the return of Entity::CreateEntity() is moved, but no std::move() is needed as the return is already prvalue.
CodePudding user response:
Just replicating the behavior of the shown lines:
m_CameraObject = std::make_unique<Entity>(Entity::CreateEntity());
This will perform a single move construction of Entity and a single move assignment of std::unique_ptr (assuming m_CameraObject is of type std::unqiue_ptr<Entity>) in addition to the non-move/copy object constructions for Entity and std::unqiue_ptr (guaranteed in C 17 or later, otherwise likely).
The std::move are not required in this, since both Entity::CreateEntity() and std::make_unique<Entity>(Entity::CreateEntity()) are already prvalues. In your original the std::move around Entity::CreateEntity() is also redundant.
However it is difficult to tell without full code whether this is what you really want to do. It may be that letting the factory function return a std::unique_ptr<Entity> directly is the better option. Then a move constructor call for Entity wouldn't be required.
