This is an interesting problem, but first discuss the compiler error.
As the compiler said, a function cannot be virtual and boilerplate. To understand why, just think about the implementation: in most cases, objects with virtual functions have a virtual table that stores a pointer to each function.
However, for templates, there are as many functions as type combinations: so what should be a virtual table? It is impossible to tell at compile time, and the memory layout of your class includes a virtual table and has one that will be determined at compile time.
Now about your problem.
The simplest solution would be to simply write one virtual method for each type, of course, it can soon become tedious, so let it pretend that you have not heard this.
If Mesh does not need to know about the various types, then you will not need the virtual function, because someone knows, given the Mesh instance, with which type the function is calling?
Mesh* mesh = ...; mesh.createChannel<int>(); // has it been defined for that `Mesh` ??
On the other hand, I believe that OpenGLMesh knows exactly what type of TypedChannel it will need. If so, we could use a very simple trick.
struct ChannelFactory { virtual ~ChannelFactory() {} virtual Channel* createChannel() = 0; }; template <class T> struct TypedChannelFactory: ChannelFactory { };
And then:
class Mesh { public: template <class T> Channel* addChannel() { factories_type::const_iterator it = mFactories.find(typeid(T).name()); assert(it != mFactories.end() && "Ooops!!!" && typeid(T).name()); Channel* channel = it->second->createChannel(); mChannels.push_back(channel); return channel; }
He demonstrates a pretty strong idiom known as type erasure . You probably used it before you knew the name :)
Now you can define OpenGLMesh as:
template <class T> struct OpenGLChannelFactory: TypedChannelFactory<T> { virtual Channel* createChannel() { return new OpenGLChannel<T>(); } }; OpenGLMesh::OpenGLMesh() { this->registerChannelFactory(new OpenGLChannelFactory<int>()); this->registerChannelFactory(new OpenGLChannelFactory<float>()); }
And you will use it like:
OpenGLMesh openGLMesh; Mesh& mesh = openGLMesh; mesh.addChannel<int>(); // fine mesh.addChannel<float>(); // fine mesh.addChannel<char>(); // ERROR: fire the assert... (or throw, or do nothing...)
I hope I understand what you need: p