有没有办法定义一个模板类,只能用于特定类层次结构中的派生类?
说我有动物基类
class Animal{
public:
virtual ~Animal();
virtual void shout() = 0;
};
和Dog,Cat,Tiger是派生类
class Dog : public Animal{
public:
virtual void shout(){
cout<<"Bark";
}
}
class Cat : public Animal{
public:
virtual void shout()
{
cout<<"Meow";
}
}
我需要定义一个模板类,说'AnimalTemplate'只能用于Animal的派生类,所以如果我尝试'AnimalTemplate&lt; Duck&gt;',我应该得到编译错误(或者一些错误),即使Duck在其中定义了一个方法shout()。 (这个问题主要是为了理解我们是否可以将OO范式与通用编程相结合)
答案 0 :(得分:4)
立即想到两种形式:
<强> SFINAE 强>
template<typename T,
typename = typename std::enable_if<std::is_base_of<Animal,T>::value>::type>
class AnimalTemplate
{
public:
AnimalTemplate() {}
};
<强> static_assert 强>
template<typename T>
class AnimalTemplate
{
public:
static_assert(std::is_base_of<Animal,T>::value, "T must be derived from Animal");
AnimalTemplate() {}
};
后者更友善地告诉你它为什么会失败,显然。
答案 1 :(得分:2)
您可以简单地定义模板,使其将模板参数用作Animal
。例如:
template <typename T,
bool = sizeof(*static_cast<Animal**>(0) = static_cast<T*>(0))>
class AnimalTemplate
{
// whatever
};
如果模板参数不匹配,则产生错误通常相当简单。如果有任何方法总是被实例化,例如析构函数,那么这也可能是支票可以去的地方。
答案 2 :(得分:0)
如果animalTemplate
是功能模板,您可以这样做:
template<typename T> void animalTemplate(T animal_candidate){
auto& animal= static_cast<Animal&>(animal_candidate);
animal.shout();
}
大多数情况下,模板会信任用户使用正确的输入。这被称为鸭子打字。 (适合您的情况!)未来C ++有关于定义 Concepts 的工作,可用于指定模板可以采用的输入类型。