Han_Chen
Han_Chen

Reputation: 305

c++ template covariance polymorphism

I am writing a generic factory class called Factory

//abstract factory
template <class C>
class Factory{
    public:
        virtual C* create()=0;
}
//concrete factory
template <class C>
class NormalFactory:public Factory<C>{
    public:

    C* create(){return new C;}
}

I want to do the following:

typedef Factory<Enemy> EnemyFactory;
EnemyFactory* e = new NormalFactory<Troll>; //Troll inherits Enemy
//client code
Enemy* enemy = e->create();

But unfortunately I can't do that since NormalFactory does not inherit Factory. Is there a way around that to accomplish what I wanted to?

(implementing an abstracted EnemyFactory without knowing the actual type of Enemy it create())

Upvotes: 0

Views: 151

Answers (2)

xaxxon
xaxxon

Reputation: 19761

You can templatize create so that you say what type of enemy it will create.

template<class T>
T * create() {
    return new T;
}

Enemy * e = my_normal_factory.create<Troll>();

In which case there's no need to templatize the class.

or this

//abstract factory
class Factory{
    public:
        virtual Enemy * create()=0;
}
//concrete factory
template <class C>
class NormalFactory:public Factory<C>{
    public:

    Enemy* create(){return new C;}
}


Factory* e = new NormalFactory<Troll>; //Troll inherits Enemy


void some_function(Factory & somefactory) {
    Enemy* enemy = somefactory->create();
}

some_function(e);

Upvotes: 0

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145279

A simple technical solution is to parameterise the concrete factory with the desired base, like this:

template <class C, class C_base = C>
class NormalFactory:public Factory<C_base>{
    public:

    C* create(){return new C;}
};

Example at Coliru.

However, the design doesn't feel right somehow. I suggest thinking about what the factories are meant to accomplish, and if there's any other more natural way of accomplishing that in C++. I.e., I think this is an XY-question.

Upvotes: 1

Related Questions