Discussion:
Virtual template function (way around it?)
(too old to reply)
ta0kira
2003-08-28 00:08:14 UTC
Permalink
I would like to make a function in an abstract class virtual, but
I can't because of a compiler error. Here is what I would like
to do:

template <class Type> struct APointer
{
template <class Type2> Type2 *PGetAs() {} //Want this virtual
};

template <class Type> struct PointerDef :
virtual public APointer <Type>
{
Type *Point;

template <class Type2> Type2 *PGetAs()
{return reinterpret_cast <Type2*> (Point);}
};

template <class Type> struct PMirror :
virtual public APointer <Type>
{
PointerDef <Type> *Original; //Want to make this 'APointer'

template <class Type2> Type2 *PGetAs()
{return Original->PGetAs <Type2*> ();}
//If 'Original' is APointer, I get access errors trying to use
//the resulting pointer
};

I would add 'Point' to APointer and then define the function body
of 'PGetAs()' in APointer, but I do not want the wasted pointer
in PMirror, and I want to re-define the function there as well.
Is there a way to use allow a template function to be re-defined
and accessed thru an abstract pointer? Thanks.
ta0kira
Chris Uzdavinis (TeamB)
2003-08-28 17:09:30 UTC
Permalink
Post by ta0kira
template <class Type> struct APointer
{
template <class Type2> Type2 *PGetAs() {} //Want this virtual
};
The C++ language explicitly prohibits templatized virtual functions.

But C++ does allow covariant return types in virtual functions.

class Base
{
public:
virtual ~Base() { }
virtual Base * foo() { return this; }
};

class Derived : public Base
{
virtual Derived * foo() { return this; }
};


Notice that Derived::foo() returns a different type than the base
class does. This is only allowable because Derived* can be converted
to Base*, and due to inheritance they're considered covariant types.

Maybe that's useful to you?
--
Chris(TeamB);
ta0kira
2003-08-28 18:26:51 UTC
Permalink
I do have a virtual function like you showed, which returns the
pointer in the form of 'Type' as used in the template. The idea
of the second function ('Type2 *PGetAs()') is to reinterpret
cast the pointer and return as a second type, such as that of a
parent class:

DERIVED_CLASS ONE;
PointerDef <DERIVED_CLASS> P_ONE;
P_ONE.Point = &ONE;

BASE_CLASS *TWO = P_ONE.PGetAs <BASE_CLASS> ();

void *THR = P_ONE.PGetAs <void> ();

This will work fine, however I could not do this:

APointer *FOU = &ONE;

BASE_CLASS *FIV = FOU->PGetAs <BASE_CLASS> ();
ta0kira
2003-08-29 00:48:46 UTC
Permalink
There is a lot of background, but basically what it comes down
to is I need to be able to cast any pointer to and from a
void**. Sorry about not including the template param in my last
post. The reason for void** and not void* is the class that
holds the pointer has a function Get() which returns *Point. If
the class stores a void* it will not compile because you cannot
create an instance of void, therefore void** is used.
The reason for casting any type of pointer to void** is so I can
have a non-template class that can hold any type of pointer, and
the function GetAs() will be used in a template function as
follows (removed refs to APointer to simplify):

template <class Type> struct PointerDef
{
Type *Point;

template <class Type2> Type2 GetAs() //Different function
{return *(reinterpret_cast <Type2*> (Point));}
};

template <class Type> struct PMirror
{
PointerDef <Type> *Original;

template <class Type2> Type2 GetAs() //Different function
{return Original->GetAs <Type2> ();}
};

class XNode
{
private:
PMirror <void*> *Item;

public:
template <class Type> SetItem(PMirror <Type> *iItem)
{
Item = reinterpret_cast <PMirror <void*>* > (iItem);
}

template <class Type, class Return> Return Eval(Return
(Type::*fFunction)()) //Eval function against pointer
{
return (Item->GetAs <Type> ().*fFunction)();
}
};

XNode::Eval() works exactly how I want it to if 'Original' in
PMirror is type 'PointerDef*', but I get access errors if
it is type 'APointer*'. I am fine leaving it as it is, but my
main concern was since I will have the same template functions
in all derivatives of APointer, I would like them to be
available when using an APointer*. Thanks for the help.
ta0kira

Continue reading on narkive:
Loading...