如何正确声明自引用模板类型?

时间:2011-06-01 23:03:01

标签: c++ templates

如何声明引用自身的模板化类型?

template <class T = Animal> class Animal
{
public:
    T getChild ();
}

有了这个,我得到一个关于缺少类型说明符的编译器错误。我试图转发声明Animal,但没有成功。

我试图强加一个类型约束。 Lion作为孩子只能有LionBearBear,依此类推。

修改

我将发布部分实际课程。它是可以出现在链表中的类的模板:

template <class T = Linked<T> > class Linked
{
private:
    T* m_prev;
    T* m_next;
}

我想强制该类只能指向同一个类(或子类)的对象。

4 个答案:

答案 0 :(得分:4)

在这种情况下,您需要在typename定义中为Animal指定一些类型参数,否则它将是类型构造中的“无限递归”:

template<class T> class Animal;//you'll need this forward declaration

template <class T = Animal<int> > class Animal //int is just an example
{
public:
    T getPrey ();
}

答案 1 :(得分:4)

OP已被回答,但我想插话,因为问题的直接原因不是递归,正如其他人所说的那样。这不起作用的最简单的原因是类模板是不是类型。它们是模板。同样,功能模板也不是功能。所以这一切都是荒谬的:

template<typename T> int function_template(int);
typedef int function_type(int);
void eats_a_function(function_type&); // needs a reference to function

std::vector< std::vector > vec0; // std::vector is not a type
std::vector< std::list > vec1; // std::list is not a type
eats_a_function(function_template); // function_template is not a function

请注意,在vec1案例中,std::liststd::vector无关。在实例化时完全定义模板(假设包含头)。它仍然无法运作。

相反,以下工作:

std::vector< std::vector<int> > vec2; // std::vector<int> is a type
std::vector< std::list<double> > vec3; // std::list<double> is a type
eats_a_function(function_template<long>); // function_template<long> is a function

请注意,在vec2的情况下,可以传递模板本身的实例化。


为了记录,玩具解决了玩具问题,写了一个引用自己的模板,使用间接的谚语层:

// expects a template that expects a type
template<template<class> class T> struct indirection {};

// forward decl. for defaulting the parameter
template<typename T> struct recursive;

// template that expects a type
template<typename T = indirection<recursive> > struct recursive {};

考虑到模板可能存在的一些事情(T内的indirection参数),这不是非常强大。当然可以编写一个rebind样式的元函数来返回T的实例化。

答案 2 :(得分:1)

您无法创建模板类,其中模板类型是类本身。这是编译器无法缓解的逻辑递归。由于模板需要编译器在遇到特定类型时构造对象(比如Animal),因此您必须具有模板类型的完整定义。否则,编译器将递归尝试构造对象。由于您的对象是自引用的,因此这将是一个非终止递归。

这个用例似乎更适合继承而不是模板。

这样做可以让你编译:     模板类动物     {     上市:         T getPrey();     }

或者,如果你真的不是默认参数:

template <class T=Cheetah> class Animal
{
public:
    T getPrey ();
}

然而,猎豹绝不能将自己或动物作为其潜在的模板类型之一。

答案 3 :(得分:1)

执行类似链接列表的常用方法是:

template <class T> class Linked
{
private:
    Linked<T>* m_prev;
    Linked<T>* m_next;
}

这对你有用吗,如果没有,你想要完成的是不能用这种方式完成的?