我有一个模板类:
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 *?
答案 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*"
);
// ...
}
答案 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
才会编译。否则,由于转换无效,它将失败。
当然,这是一个非常简单的例子,可能会忽略一些好的设计元素。但原则就在那里,这是我目前唯一知道产生这种模板参数约束的方法。