Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is recursive explicit template instantiation possible?

Tags:

c++

templates

Given a template like

template<int dim> class Point { ... };

this template can be instantiated explicitly like

template class Point<0>;
template class Point<1>;
template class Point<2>;
template class Point<3>;

instead of instantiating every template individually like above, I would like to instantiate them recursively with one call like

template class RecursiveInstantiate<Point, 3>;

where RecursiveInstantiate<T, i> would instantiate T<i>, T<i-1>, ..., T<0>. Is it somehow possible to create such a class RecursiveInstantiate? If it is not possible, do you know a way to do it with the preprocessor?

In fact I am interested in generalizing this for classes with multiple template parameters likeNode<int i1,int i2,int i3> for all combination of i1,i2,i3 in {0,1,2,3}. But I hope to be able to work out this second part by myself.

Any advice, also an explanation why it is impossible what I want to achieve is appreciated.


Update: thank you for your comments so far. I see now more clearly where the problem really is. The line

template class Point<3>;

instantiates the template and exports its symbols to the object file. An instantiation of the form

template class RecursiveInstantiate<Point, 3>;

may instantiate the classes class Point<3>, class Point<2>, .... Apparently this only happens locally though. The templates are not exported to the object file. Maybe I will have to look for a solution using the preprocessor.

As I see now that I did not ask my question precisely enough in the beginning, I appreciate your answers and selected ones as correct.

Note: I am trying this on linux with g++/clang as compilers.

like image 444
H. Brandsmeier Avatar asked Sep 12 '11 23:09

H. Brandsmeier


2 Answers

You could make a little Instantiator class:

template <unsigned int N> struct Instantiator
{
  Point<N> p;
  Instantiator<N-1> i;
};

template <> struct Instantiator<0>
{
  Point<0> p;
};

Then simply add one explicit instantiation: template struct Instantiator<81>;

You can extend this idea lexicographically to any number of integral parameters.


As @Georg says, let's make it generic:

template <template <unsigned int> class T, unsigned int N> struct Instantiator
{
  T<N> t;
  Instantiator<T, N-1> i;
};

template <template <unsigned int> class T> struct Instantiator<T, 0>
{
  T<0> t;
};

template struct Instantiator<Point, 82>;
like image 141
Kerrek SB Avatar answered Nov 15 '22 06:11

Kerrek SB


You can do that like this:

template<int dim> struct Point {
    static const int val = dim;
    Point<dim - 1> p;
};

template<> struct Point<0> { ... };

That creates a template specialisation for the template parameter when it is 0 so the recursion stops there, and when you instantiate one like this:

Point<4>

It instantiates from Point<4> down to Point<0>. Then you can do

Point<4>::val

to access the value of that particular one.

like image 22
Seth Carnegie Avatar answered Nov 15 '22 06:11

Seth Carnegie