views:

56

answers:

1

Hi,

Im not sure if this can be done, im just delving into templates so perhaps my understanding is a bit wrong.

I have a Platoon of soldiers, the platoon inherits from a formation to pick up the formations properties, but because i could have as many formations as i can think of I chose to use the CRTP to create the formations, hoping that i could make a vector or array of Platoon to store the platoons in. but, of course, when i make a Platoon, it wont store it in the vector, "types are unrelated"

Is there any way around this ? i read about "Veneers" which are similar and that they work with arrays but i cant get it to work, perhaps im missing something.

here's some code: (sorry about the formatting, the code is here in my post but its not showing up for some reason )

template < class TBase >
class IFormation 
{
public : 
~IFormation(){}

bool IsFull()
{
    return m_uiMaxMembers == m_uiCurrentMemCount;
}
protected:
    unsigned int m_uiCurrentMemCount;
    unsigned int m_uiMaxMembers;
    IFormation( unsigned int _uiMaxMembers  ): m_uiMaxMembers( _uiMaxMembers ), m_uiCurrentMemCount( 0 ){}      // only allow use as a base class.

    void SetupFormation( std::vector<MySoldier*>& _soldierList ){}; // must be implemented in derived class
};
/////////////////////////////////////////////////////////////////////////////////
// PHALANX FORMATION
class Phalanx : public IFormation<Phalanx>
{
public:
Phalanx( ):
  IFormation( 12 ),
  m_fDistance( 4.0f )
{}

~Phalanx(){}


protected:
float   m_fDistance;        // the distance between soldiers
void    SetupFormation( std::vector<MySoldier*>& _soldierList );
};
///////////////////////////////////////////////////////////////////////////////////
// COLUMN FORMATINO
class Column : public IFormation< Column >
{
public :
Column( int _numOfMembers ):
   IFormation( _numOfMembers )
   {}

~Column();
protected:
void    SetupFormation( std::vector<MySoldier*>& _soldierList );
};

I then use these formations in the platoon class to derive, so that platoon gets the relevant SetupFormation() function:

template < class Formation >
class Platoon : public Formation
{
public:
**** platoon code here
};

everything works great and as expected up until this point.

now, as my general can have multiple platoons, I need to store the platoons.

typedef Platoon< IFormation<> > TPlatoon; // FAIL
typedef std::vector<TPlatoon*>  TPlatoons;
TPlatoon            m_pPlatoons

m_pPlatoons.push_back( new Platoon<Phalanx> ); // FAIL, types unrelated.

typedef Platoon< IFormation<> > TPlatoon; fails because i need to specify a template parameter, yet specifying this will only allow me to store platoons created with the same template parameter.

so i then created FormationBase

class FormationBase
{
public:
    virtual bool IsFull() = 0;
    virtual void SetupFormation( std::vector<MySoldier*>& _soldierList ) = 0;
};

and made IFormation publicly inherit from that, and then changed the typedef to

typedef Platoon< IFormation< FormationBase > > TPlatoon;

but still no love.

now in my searches i have not found info that says this is possible - or not possible.

A: 

C++ does not allow simple use of compile time and run time polymorphism. You are correct in that your vector is only able to hold one type. You're going to have to have your vector store a pointer to a non template type, or change the design to not use a vector.

If you want to have the CRTP'd classes publicly inherit from FormationBase, then the vector would have to be a std::vector<FormationBase *>. It's impossible to go back from the runtime class FormationBase to the compile time template parameters it was instantiated with.

Considering your data looks relatively consistent and you merely want to change how your algorithm arranges the soldiers and units on the battlefield, I'd consider using the strategy pattern to specify the SetupFormation function, and have a separate, nonpolymorphic class using that which you store in the vector.

Billy ONeal
thanks, i've changed things around to use the "strategy pattern" as you suggest and it achieves what i wanted. thanks for the tip on the strategy pattern.note to self: dont try and implement unfamiliar patterns when time is crucial ;)
Simon Dobie