0

Class World is designed to spawn Actors.
Actors can be different types: it's can be Cat, can be Dog, can be Tree, everything, the only similar thing is that they all derived from Actor.
And there is also command line, it gives World a string where written next things:
what_to_do string_leftover. There if what_to_do equals "Spawn" then first word of string_leftover must be type name, second - Actor name.
The problem is that number of Actors can be indefinite - I don't really sure about their count and I'am really scared of forget to write their Spawn overload manually.

If very simple:
I entered in console: "SelectWorld World1" then "Spawn PhysicalPendulum OneMorePendulum". This will select world named World1 (this is working perfectly) and spawn Actor of type PhysicalPendulum with name OneMorePendulum.
Problem: I can't elegantly determine what type I should spawn from string.
Why:
All solutions I know requires to create "string to type determiners" not in actor-derived class header/object file.
I mean I can use switch (pointer-to-function map), but each time I create new Actor type I need to return to that Spawn function and write down new type to spawnables, there is a slight chance that I can totally forget about it and looooooong time of debugging will be awaiting me.
I can create static class instance with macro, but there is no guarantee that Spawner will be created before this instance initializes.
I thought about tricks with macros, but they can't be extended, like if certain define had "definition_body" I can't add "another_definition_body" to it and get "definition_body another_definition_body".
How can I elegantly spawn type from string?

Mr Hungry
  • 46
  • 3

2 Answers2

0

For your code to create an object, you must know the type of the object you are creating. At some point you must say thing* = new Thing() You can have a factory that knows all the types of objects allowed to be created. If you use a standardised naming convention you can use token pasting. thing* = new Thing ## string_name. i.e. string = "Robot". #define ABC(name) return new Thing ## name. class ThingRobot {}; etc...

dgsomerton
  • 105
  • 5
0

Declare a global function/macros that will 'register' newly create class to the list of known e.g.

//SpawnActor.h
#pragma once
using std::string;
using std::map;
using std::function;
class Actor;

class ActorSpawner
{
public:
    typedef function<Actor()> SpawnFunction;
    static void RegisterActorClass(const string& name, const SpawnFunction& function)
    {
        s_spawnClasses[name] = function;
    }

    void SpawnClass(const string& name)
    {
        // You'll need to validate name
        Actor* a = s_spawnClasses[name]();
        //...
    }

private:
    static map<string, function<Actor()> s_spawnClasses
};


//SpawnActor.cpp
#include "SpawnActor.h"
map<string, function<Actor()> SpawnFunction::s_spawnClasses();


//TreeActor.h

class TreeActor : public Actor
{
    ...
};


//TreeActor.cpp
#include "TreeActor.h"

ActorSpawner::RegisterActorClass("TreeActor", [](){return new TreeActor();})
Teivaz
  • 5,462
  • 4
  • 37
  • 75