views:

117

answers:

3

I have just read an article about the Curiously Recurring Template Pattern. And you can use it simulate virtual function with templates.

For example:

template<class T>
struct A
{
    void func() { static_cast<T*>(this)->func(); }
};

struct B : public A<B>
{
    void func() { cout << "B" << endl; }
};`

However, if we have many subclasses from A and want to put them all in vector, for example vector<A*> this is not possible when you use templates and you have to use normal polymorphism with virtual functions in the base class.

Does anyone have a design suggestion to solve this? Because I want to use templates but also be able to but all subclasses together in a container.

+1  A: 

Define a non-template abstract base class for your template class. Use the base class for working with containers.

raffel
+5  A: 

You could do this:

class NonTemplateBase
{
};

template<class T>
struct A : public NonTemplateBase
{
    void func() { static_cast<T*>(this)->func(); }
};

and then create a vector of pointers to NonTemplateBase (i.e. std::vector<NonTemplateBase *>).

However, I'm guessing you want to be able to call func() or other member functions on the objects in your vector -- and you want those calls to polymorphically call the correct member function in the derived class.

This isn't going to work because the Curiously Recurring Template Pattern only allows you to do static (i.e. compile-time) polymorphism. If you want runtime polymorphism, you have to use virtual functions.

Martin B
+1: beat me on runtime polymorphism
onof
A: 

Have all your templates implement a common interface and create a vector of pointers or references to that interface.

class Icommon //interface
{
public:
    virtual void print() = 0;
};

template <class T>
class MyCommon : public Icommon
{
    T obj;

public:
    MyCommon(T o):obj(o) {}

    void print() {cout << obj;}
};

main()
{
    MyCommon<int> i(1);
    MyCommon<char> c('t');

    vector<Icommon *> commonVec;

    commonVec.push_back(&i);
    commonVec.push_back(&c);
}