I have a templated class, CDerived:
template <typename TValue, typename TDraw, typename TEdit ...>
class CDerived : public CBase
{
TValue m_Value
public:
TValue& GetValue() const
{
return m_Value;
}
void Draw()
{
TDraw::Draw(this);
}
void Edit()
{
TEdit::Edit(this);
}
};
It is designed as a generic class that is constructed by passing in various "policy classes" as template arguments (different composite types are created using typedefs). I need to store pointers to CDerived objects in a container.
In order to accomplish this, I've created a non-templated CBase from which CDerived derives, in order to store the CBase* pointers in the container, since the container cannot store CDerived* pointers since they are not all of the same type due to the template arguments of CDerived.
I have a few pure virtual functions in CBase that are overriden in CDerived. In it's implementation, CDervied just makes calls to the policy classes static methods, passing in it's this pointer. This works fine as long as the virtual functions in CBase and CDerived have the same signatures (parameter types and return type).
My problem occurs in that one of the template members passed into CDerived is a Value that it holds. Value can be any arbitrary object, not necessarily a POD type. The only rule is that the TDraw, TEdit, etc. must be able to handle the TValue type.
I need to be able to call GetValue() in the container, but since the container only holds CBase* objects, it can't call GetValue(). GetValue() cannot be a virtual function because the return type is variable depending on the TValue template argument in CDerived. It cannot be a templated virtual function because templated virtual functions are not allowed (MSVC). It cannot be a simple template function because CBase does not know the return type and CBase cannot be templated if stored in a homogenous container.
I've experimented with many different approaches, including handle classes, visitor objects, chameleon objects, etc.; none of which work.
None of these work because in all cases you need to know the target types beforehand, and I don't know all of the target types because CDerived is templated with exponential combinations of template types.
It's interesting that sizeof() and typeid() obviously are able to figure out the type of the derived class from a base class pointer, but there appears to be no support in the language for figuring this out.
What I need to do is either:
1) Given a CBase* pointer, in a container that does not know beforehand what specific CDerived is pointed to, get a CDerived* pointer and be able to call methods on that pointer.
2) Have a way to store CDerived* objects on a container and get the properly-typed pointer out in the container and call methods on it (without the container knowing the pointer's type beforehand, just that the pointed-to object does implement the methods, such as GetValue() that will be called by the container).
I have a feeling that there must be some way to do this, though I have not seen anything that indicates it is possible.
Does anyone have any ideas?
~Mike