0

有没有办法定义一个模板类,它只能与来自特定类层次结构的派生类一起使用?

说我有动物基类

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< Duck >',我应该得到编译错误(或一些错误),即使Duck在其中定义了一个方法shout()。(这个问题主要是让我了解我们是否可以将 OO 范式与通用编程相结合)

4

3 回答 3

4

立即想到两种形式:

SFINAE

template<typename T, 
         typename = typename std::enable_if<std::is_base_of<Animal,T>::value>::type>
class AnimalTemplate
{
public:
    AnimalTemplate() {}
};

静态断言

template<typename T>
class AnimalTemplate
{
public:
    static_assert(std::is_base_of<Animal,T>::value, "T must be derived from Animal");
    AnimalTemplate() {}
};

显然,后者更友好地告诉您失败的原因。

于 2013-10-28T23:23:35.180 回答
2

您可以简单地定义您的模板,使其使用模板参数作为Animal. 例如:

template <typename T,
          bool = sizeof(*static_cast<Animal**>(0) = static_cast<T*>(0))>
class AnimalTemplate
{
    // whatever
};

在模板参数不匹配的情况下产生错误通常是微不足道的。如果有任何方法总是被实例化,例如析构函数,那也可能是检查的地方。

于 2013-10-28T23:19:35.413 回答
0

如果animalTemplate是一个函数模板,你可以这样做:

template<typename T> void animalTemplate(T animal_candidate){
   auto& animal= static_cast<Animal&>(animal_candidate);
   animal.shout();
}

大多数情况下,模板信任用户使用正确的输入。这被称为鸭子打字。(适合你的情况!)未来的 C++ 有定义Concepts的工作,它可用于指定模板可以接受的输入类型。

于 2013-10-28T23:27:21.497 回答