TMcSquared
TMcSquared

Reputation: 107

can a std::list contain different std::unique_ptr<T>?

So, I'm making a game manager class for Qub3d Engine, and I want each GameState to be an std::unique_ptr

Each GameState such as mainMenu that I have is a child class of GameState

I need std::list(or something) to contain different unique_ptrs for each state such as mainMenu and mainGame.

I've tried std::list< std::unique_ptr<GameState> > stateStack;, but when I try to do this: stateStack.push_back(m_mainMenu); I get an C2664 error about the overload not including the mainMenu class. (Don't know if this is relevant, but I'm using MSVC)

How would I accomplish this? And is this even possible?

Upvotes: 0

Views: 77

Answers (1)

CodeMouse92
CodeMouse92

Reputation: 6898

It's absolutely possible, but you need to change how you think of pointers for this.

A unique_ptr meant as a guarantee that there will only be one pointer to the object. It manages the lifetime of the object it points to, and thus helps prevent possible memory errors and mistakes.

Thus, a unique_ptr should be defined within the context it lives. You can't just hand a random pointer to a data structure and have it become a unique_ptr.

In the terms of std::vector, you can use the emplace_back() function in combination with the new operator. This function actually handles the initialization of the object in question, as opposed to push_back(), which only adds an existing object to the data structure.

std::vector<std::unique_ptr<Dog>> dogshow;
dogshow.emplace_back(new Dog());
dogshow[0]->speak();  // outputs "woof", consistent with my Dog class.

Quite simply, the emplace_back function takes over the declaration of the unique_ptr.

If you absolutely want to use std::list instead, that offers an analogous emplace function. Many C++ standard data structures do.


NOTE: If you want the smart memory management of unique_ptr, but want to have multiple pointers to the same object, you should look at shared_ptr.

Upvotes: 2

Related Questions