But can I call particle methods or attributes from the templated manager this way? |
You can call them directly. The compiler will remind you when you try to call something that isn't in the template type once he tries to compile the particular instance.
This also means, that you don't get compile errors unless you actually use the particle manager.
Another, option could be that you provide a base class Particle Manager who has abstract functions for copying and creating particles and these are implemented in a derrived template that needs its template type only for calling the right constructors.
I'll sketch it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
struct Particle {
virtual ~Particle() {} // you want virtual destructors when destroying objects over their base pointer!
virtual void update();
...
};
struct SpecializedParticle : Particle {
...
};
struct BaseParticleManager
{
virtual Particle* createParticle() = 0;
virtual Particle* copyParticle(Particle*) = 0;
virtual void deleteParticle(Particle*) = 0;
};
template<class T>
struct ParticleManager : BaseParticleManager
{
virtual Particle* createParticle() { return new T; };
virtual Particle* copyParticle(Particle* p) { return new T(p); }
void deleteParticle(Particle* p) { delete p; }
};
...
// later in the code
ParticleManager<SpecializedParticle> myParticleManager;
...
|
As you can see, the ParticleManager template is only responsible for copying and constructing the particles and you can implement the "normal" functions like you are used to it in the BaseParticleManager without any hazzle that comes with developing templates. (Like they always have to be in header files, take a full recompile everytime you sneeze, bad error messages and so on).
Should you encounter a special particle that needs to be constructed differently, you can specialize the template for this struct.
The solution as I presented it here has a very big performance problem: Every single particle is created on the heap separately. You have to accept this when you want to use any virtual-function based polymorphism in your Particles*), but for a lightweight-struct like particles in a game engine, this is a big blow (not because of virtual function calls but because of memory spreading. You can compensate with custom operator new's but that's really an advanced topic).
Ciao, Imi.
*) Edit: Not necessarily true, but it will be hard and full of ugly edges if you try to allocate polymorph-behaving objects in continous memory blocks.