How to properly declare a self-referencing templat

2020-04-06 16:03发布

How do I declare a templated type that refers to itself?

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

With this, I get a compiler error concerning a missing type specifier. I tried to forward-declare Animal, without success.

I am trying to impose a type constraint. A Lion can only have a Lion as a child, a Bear has a Bear, and so on.

EDIT

I'll post part of the actual class. It is a template for classes that can appear in a linked list:

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

I want to enforce that the class can only point to object of the same class (or a subclass).

标签: c++ templates
4条回答
\"骚年 ilove
2楼-- · 2020-04-06 16:24

The usual way to do something like a linked list is:

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

Does this work for you, and if not, what are you trying to accomplish that can't be done this way?

查看更多
淡お忘
3楼-- · 2020-04-06 16:34

The OP has been answered but I want to chime in because the immediate cause of the problem is not recursion, as others claim. The simplest reason this wouldn't work is that class templates are not types. They are templates. Similarly, function templates are not functions either. So all of this is nonsensical:

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

Notice that in the vec1 case, std::list is not related to std::vector. The template is fully defined (assuming header inclusion) at the point of instantiation. It still won't work.

Instead, the following works:

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

Notice that in the vec2 case, it's fine to pass an instantiation of the template itself.


For the record, a toy solution to the toy problem on writing a template that refers to itself, using the proverbial layer of indirection:

// 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 {};

Not terribly powerful given the few things that are possible with a template (the T parameter inside indirection). It's of course possible to write a rebind-style metafunction that returns an instantiation of T.

查看更多
ら.Afraid
4楼-- · 2020-04-06 16:35

In this case, you need to specify some type parameter to Animal in your typename definition, or else it would be an "infinite recursion" in the type construction:

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 ();
}
查看更多
够拽才男人
5楼-- · 2020-04-06 16:39

You can't create a template class wherein the template type is the class itself. This is a logical recursion that your compiler can't mitigate. Since templates require the compiler to construct the object when a specific typing is encountered ( say Animal ), you have to have a complete definition of the template type. Otherwise, the compiler will recursively try to construct objects. Since your object self-references, this will be an non-terminating recursion.

This use-case seems much more appropriate for inheritance than for templates.

Doing this will let you compile: template class Animal { public: T getPrey (); }

Or, if you really wan't a default argument:

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

Yet, cheetah must not use itself or Animal as one of its potential template types.

查看更多
登录 后发表回答