Mr. Boy
Mr. Boy

Reputation: 63720

Recursive template pattern; when is type finalized?

Linked to my other question (Can I make an assignment operator on a base class that returns sub-class type) I have this construct, the idea is I want to derive specialized types from GPtrBase without having to re-write an assignment operator every time:

template<class BaseType,class Self>
class GPtrBase
{
public:
    ...

    Self& operator=(const BaseType& rhs)
    {
        ...
        return *this;
    }

};

However when I specialize like:

class GDrawablePtr : public GPtrBase<MyDrawable,GDrawablePtr>

I get errors:

'return' : cannot convert from 'GPtrBase<Base,Self>' to 'GDrawablePtr &'

I thought a template class was generated based on the specializations used, so shouldn't *this be of type GDrawablePtr in the first place?

updated: I note if I add using GPtrBase::operator=; it then works, even though GDrawablePtr definitely does not define any operators.

Upvotes: 1

Views: 125

Answers (2)

TemplateRex
TemplateRex

Reputation: 70526

In contrast to dynamic polymorphism where the this-pointer in virtual functions is automatically downcast from base to derived, you need to use an explicit static_cast to the derived class

template<class BaseType,class Self>
class GPtrBase
{
public:
    ...

    Self& operator=(const BaseType& rhs)
    {
        ...
        return static_cast<Self&>(*this);
    }

};

Upvotes: 2

NonNumeric
NonNumeric

Reputation: 1109

I thought a template class was generated based on the specializations used, so shouldn't *this be of type GDrawablePtr in the first place?

It seems you put more into template instantiation than there actually is. A class template is just that: a template that when given its arguments generates a class. It doesn't bind the template arguments to the resultant class in any additional way.

In particular, the fact that you are inheriting from the instantiated class at the point of instantiation doesn't change anything in the class's definition. It is still independent class with it's own (albeit somewhat complicated) type and as such it is no different than any other base class defined without template machinery. For example there is no implicit conversion from pointer to base class to pointer to any of its subclasses regardless of how the base or the subclasses were created.

Upvotes: 0

Related Questions