I want to implement a Mesh class for a CG project, but have run into some problems.
What I want to do is a Mesh class that hides implementation details (like loading to a specific API: OpenGL, DirectX, CUDA, …) from the user. Additionally, since the Mesh class will be used in research projects, this Mesh class has to be very flexible.
class Channel {
virtual loadToAPI() = 0;
}
template <class T>
class TypedChannel : public Channel {
std::vector<T> data;
};
template <class T>
class OpenGLChannel : public TypedChannel<T> {
loadToAPI(); // implementation
};
class Mesh {
template<class T>
virtual TypedChannel<T>* createChannel() = 0; // error: no virtual template functions
std::vector<Channel*> channels;
};
class OpenGLMesh {
template<class T>
TypedChannel<T>* createChannel()
{
TypedChannel<T>* newChannel = new OpenGLChannel<T>;
channels.push_back(newChannel);
return newChannel;
};
};
For flexibility, each Mesh is really a collection of channels, like one position channel, a normal channel, etc. that describe some aspects of the mesh. A channel is a wrapper around a std::vector with some added functionality.
To hide implementation details, there is a derived class for each API (OpenGLMesh, DirectXMesh, CUDAMesh, …) that handles API-specific code. The same goes for the Channels (OpenGLChannel, etc. that handle loading of the Channel data to the API). The Mesh acts as a factory for the Channel objects.
But here is the problem: Since the Channels are template classes, createChannel must be a template method, and template methods cannot be virtual. What I would need is something like a Factory Pattern for creating templated objects. Does anyone have advice on how something similar could be accomplished?
Thanks
It’s an interesting problem, but let’s discuss the compiler error first.
As the compiler said, a function cannot be both virtual and template. To understand why, just think about the implementation: most of the times, objects with virtual functions have a virtual table, which stores a pointer to each function.
For templates however, there are as many functions as combinations of type: so what should be the virtual table like ? It’s impossible to tell at compilation time, and the memory layout of your class includes the virtual table and has to be decided at compilation time.
Now on to your problem.
The simplest solution would be to just write one virtual method per type, of course it can soon become tedious, so let’s pretend you haven’t heard that.
If
Meshis not supposed to know about the various types, then surely you don’t need the function to bevirtual, because who would know, given an instance ofMesh, with which type invoking the function ?On the other hand, I will suppose that
OpenGLMeshdoes know exactly which kind ofTypedChannelit will need. If so, we could use a very simple trick.And then:
It demonstrates a quite powerful idiom known as
type erasure. You probably used it even before you knew the name 🙂Now, you can define
OpenGLMeshas:And you’ll use it like:
Hope I understood what you needed :p