Creating a library with a list of unknown template types

125 views Asked by At

A while back, I began creating games and I ran into a style that I really like. It's called component based architecture. The tutorial is for Objective-C, not C++, but I included the link anyways: http://www.raywenderlich.com/24878/introduction-to-component-based-architecture-in-games

I noticed that I was copying and pasting a lot of code from project to project, so I decided to just create a library for the general framework. Typically the components are included in an entity object, like so:

#ifndef ENTITY_H
#define ENTITY_H

#include "HealthComponent.h"
#include "MoveComponent.h"
#include "PlayerComponent.h"
#include "RenderComponent.h"

class Entity
{
public:
    Entity();

    HealthComponent* getHealth();
    //Returns a reference to the object's health component
    //If there is none, returns a null pointer

    MoveComponent* getMove();
    //Returns a reference to the object's movement component
    //If there is none, returns a null pointer

    PlayerComponent* getPlayer();
    //Returns a reference to the object's player component
    //If there is none, returns a null pointer

    RenderComponent* getRender();
    //Returns a reference to the object's render component
    //If there is none, returns a null pointer

    ~Entity();
private:
    HealthComponent* health;
    MoveComponent* move;
    PlayerComponent* player;
    RenderComponent* render;
};

#endif //ENTITY_H

Since my library will contain the general framework, not the individual components, this method doesn't work any more. Instead, I created a ComponentManager class to manage my components. Currently, an entity looks like this:

#ifndef ENTITY_H
#define ENTITY_H

#include "Component.h"
#include "ComponentManager.h"
#include <list>

class Entity
{
public:
    Entity();
    Entity(ComponentManager const & cmanager);
    template <T>
    T* getComponent();
    //Returns the first component of the specified type
    //If there is none, returns NULL

    template <T>
    T* getComponent(int i);
    //Returns the ith component of the specified type
    //If the component does not exist, returns NULL

    template<T>
    int getComponentCount();
    //Returns the number of components of the specific type that the
    //entity contains

    template <T>
    int addComponent(T &component);
    //Adds a component of the specified type to the class. If a component of the
    //class already exists, the component is assigned a number, and the number is returned.
    //If no components of the class exist, 0 is returned

    ~Entity();
private:
    int eid;
    std::list<ComponentReference> components;
    ComponentManager * manager;
};

#endif //ENTITY

I haven't defined these functions yet, so I didn't include the implimentation file.

The ComponentReference struct simply is a collection of ints and strings used to locate the particular component. The entity would pass a ComponentReference to a templated function in manager, which would search its internal list for the particular object. And there's the brick wall. I don't know how I would create a list containing an unknown number of objects of differing unknown types. They ARE derived from a parent Component class, but they all contain different functions and member variables. I tried to use an array of pointers and typecasting, but I gave up after three hours when I read that an over reliance on typecasting is an indicator of badly written code.

I tried using STL containers, but they need only one type, so apparently they won't work (C++ std::vector with pointers to a template class)

I saw something about wrappers, but from what I read, they appear to only work with functions: (c++ store a pointer to a member function of unknown class) If they could be used to solve my problem, please explain how they work (I've never heard of them before today)

Since this is my first question, feel free to leave feedback. I did research, but if this is a duplicate, I'm sorry. I'm not new to C++, but I am also not an expert, and it is a big language, so I may ask for clarification. Thanks in advance!

0

There are 0 answers