I am currently programming something where I hit this problem:
I have a Scene
class and a MainScene
class:
class Scene{
Scene();
}
class MainScene : public Scene{
MainScene();
}
And what I want to do is keep track of a list of scenes like this:
std::map<std::string, Scene*> scenes;
And I add a scene to it like this:
MainScene* mainscene; //I do not make it a new because i want my scenemanager to handle that
scenes.emplace("mainscene", mainscene); // add it to the list
and I have a function like this:
template <class T>
void SceneManager::recreateScene(T* &scene)
{
scene = new T();
}
So that when I want to use a function loadscene
, I can grab the scene from the list and delete the current scene and create the new scene with the function recreateScene
. But the map gives me Scene
. So when I use recreateScene
it calls the constructor of Scene()
instead of MainScene()
. But I need it to know that the scene in the list is a MainScene
so it creates a new MainScene()
instead of a new Scene()
.
One way to do that is to store the creator alongside the pointer. Something like this:
std::map<std::string, std::pair<Scene*, std::function<Scene*()>> scenes;
scenes.emplace("mainscene", {nullptr, []() { return new MainScene(); }});
Then, modify recreateScene
:
template <class T>
void SceneManager::recreateScene(Scene* &scene, std::function<Scene*()> creator)
{
scene = creator();
}
// called as:
auto& s = scenes["mainscene"];
recreateScene(s.first, s.second);
Side note: If these pointers own the Scene
object, they should not be raw pointers, but std::unique_ptr<Scene>
instead. DTTO for the return type of the std::function
.