Proxy class for polymorphic type, using templates


Keywords:c++ 


Question: 

This is for a "game engine" as a bit of programming practice. All of my GameObjects are component based, where each component adds a functionality to its parent GameObject and all of these components descend from a base Component class which has virtual methods making it polymorphic.

When I read in these gameobject definitions from an XML file some components need to know about others for example a physics component needs to be aware of the transform component for the physics calculations. However if these components aren't present in the XML file then occasionally it throws up nasty null-pointers and endless rabbit hole call stack chasing to find the XML typo I fudged while half asleep.

My solution was to have a node in the XML file as an assertion that a component of this type should exist and possibly throw an exception or another appropriate action if it doesnt. Eg.

<ComponentRequirement type="ComponentTransform">myTransformComponent</ComponentRequirement>

So I need a way of representing this in C++. The first idea, template classes to change according to what type of component it's the proxy of since this class needs to act like their unproxied component. I've solved that with some operator overloading so long as the class is a template class.

template <class T>
class ComponentRequirement {
public:

    T* operator->() { (I chose the arrow operator because the CompReq class will never be referenced as a pointer)
        return this->component;
    }

//Other unrelated functions . . . 

private:
    T* component;
};

And this is all fine and dandy at compile time because I can just say

ComponentRequirement<ComponentTransform> req = ComponentRequirement("myComponentTransform");

But I need to be able to specify what that template type in place of the will be from a string when I read the XML in. I thought a hashmap could do it but I dont think the type name even "is" anything other than a human readable compiler hint so I couldn't use it as a hashmap value.

Can this be done and how could I go about implementing it? Inserting some string literal into a "black-box of magic" and get something that can be used as a template argument. And if it helps, everything that will be the value of "T" is polymorphic. Or is there a better solution to my problem. It needs to be able to act as any Component I put into it and it needs to be discernable at runtime.

EDIT 1:

In my components I have a read and write function. If I read the component requirement in there I can make sure the template has the right value because each component is seperate. I can then evaluate the requirements with a virtual function and a few functions in the gameobject class to check it's a valid configuration. This could solve the problem.


1 Answer: 

At a first glance I would use the factory pattern for your problem. That way you can create classes to create your objects given a different string without specifying the exact class you need at compile time unlike with normal typed constructors. The analogy I see people use are Virtual Constructors.

In essence you would have a map of factories (creator objects).

  1. Define some top level interface for your components, such as IComponent.
  2. Define a factory class for every component you want to generate that has a Create Instance method. I recommend the Create Instance method should be part of an interface like IFactory.
  3. During setup of your program create your map and assign factories to particular keys. ActorCreator["MyComponent"] = new MyComponentFactory();
  4. When you want to create an object read from an XML node you can just call the create instance method on the returned factory for the key. auto myComponent = ActorCreator[readXML]->CreateInstance();
  5. You now have an actor/components whose concrete type has been decided at runtime instead of compile time.