Search code examples
c++templates

is recursive explicit template instantiation possible?


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.


Solution

  • 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>;