“模板多态”在调用基类型的模板化参数的函数时,使用派生类型?

时间:2011-07-02 17:52:08

标签: c++ templates

我有一个模板类:

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

两个类,一个基类和一个来自它的类:

class Base
{
    //does whatever
}

class Derived : public Base
{
}

现在我想组装一个函数,它可以处理模板化类型Base *的TemplateClass以及模板化类型Derived *的TemplateClass,而不必为两种类型分别实现该函数。

在代码中,这是我希望能够做到的:

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

代码中的其他地方:

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

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

有没有办法实现这一点而不必手动重载DoSomething for Derived *?

2 个答案:

答案 0 :(得分:5)

可悲的是,C ++不支持模板协方差,因此您无法自动执行此操作。作为一种解决方法,您可以执行以下操作:

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

答案 1 :(得分:0)

如果你不反对更普遍的情况,解决这个问题很简单:

我只需在您的DoSomething函数中添加模板参数:

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

当然,这不允许您直接将参数T约束为Base的子类。但是它允许你不写几个DoSomething的重载。

修改

如果您的TemplateClass打算包装T类型的值,则可能有办法约束DoSomething的参数。

假设TemplateClass被宣布为

template<class T>
class TemplateClass
{

public:

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

    T Value;
};

然后DoSomething可以写为

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

现在,在编译期间,只有Base * b = tc.Value设置为T的子类时,行Base才会编译。否则,由于转换无效,它将失败。

当然,这是一个非常简单的例子,可能会忽略一些好的设计元素。但原则就在那里,这是我目前唯一知道产生这种模板参数约束的方法。