开发者

"template polymorphism" when calling function for templated parameter of base type, with derived type?

开发者 https://www.devze.com 2023-03-17 08:20 出处:网络
I\'ve got a template class: template <class T> class TemplateClass { //irrelevant what this class does

I've got a template class:

template <class T>
class TemplateClass
{
   //irrelevant what this class does
}

And two classes, one base and one class which derives from it:

class Base
{
    //does whatever
}

cl开发者_运维知识库ass Derived : public Base
{
}

Now I want to assemble a function which can deal with TemplateClass of templated type Base* as well as TemplateClass of templated type Derived* without having to implement the function separately for both types.

In code, this is what I'd like to be able to do:

void DoSomething(const TemplateClass<Base *> &tc)
{
   //do something
}

And somewhere else in the code:

TemplateClass<Base *> a;
TemplateClass<Derived *> b;

DoSomething(a); //Works
DoSomething(b); //Doesn't work, but I'd like it to work

Is there a way to implement this without having to manualy overload DoSomething for Derived* ?


Sadly, C++ does not support template covariance, so you cannot do that automatically. As a workaround, you could do something like this:

template <typename T>
void DoSomething(const TemplateClass<T*>& tc) {
    // in C++03, use BOOST_STATIC_ASSERT and boost::is_convertible
    static_assert(
        std::is_convertible<T*, Base*>::value,
        "Template argument must be convertible to Base*"
    );

    // ...
}

Demo on ideone.


It is simple to solve this if you are not opposed to a more general situation:

I would simply add a template parameter to your DoSomething function:

template<class T>
void DoSomething(const TemplateClass<T *> &tc)
{
}

Of course, this doesn't allow you to directly constrain the parameter T to being a subclass of Base. But it will allow you to not write several overloads of DoSomething.

Edit

If your TemplateClass was intended to wrap a value of type T, then there may be a way to constrain to parameter for DoSomething.

Suppose TemplateClass were declared something like

template<class T>
class TemplateClass
{

public:

    TemplateClass( T value )
    : Value(value)
    {
    }

    T Value;
};

Then DoSomething could be written as

template<class T>
void DoSomething( const TemplateClass<T *> &tc )
{
    Base * b = tc.Value;
}

Now, during compilation, the line Base * b = tc.Value will only compile if T is set to a subclass of Base. Otherwise, it will fail due to an invalid conversion.

Of course, this is a very simple example which may ignore some elements of good design. But the principle is there, and this is the only way I am currently aware of the produce such a constraint on a template parameter.

0

精彩评论

暂无评论...
验证码 换一张
取 消