类层次结构的模板类?

时间:2013-10-28 23:03:11

标签: c++ templates

有没有办法定义一个模板类,只能用于特定类层次结构中的派生类?

说我有动物基类

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范式与通用编程相结合)

3 个答案:

答案 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 的工作,可用于指定模板可以采用的输入类型。