Survey of the Solutions
Via Boost Preprocessor (BOOST_PP_REPEAT)
See the solution proposed by Luc Touraille
#define INSTANTIATE(_, n, type) template class type<n>;
#define INSTANTIATE_N(n, type) BOOST_PP_REPEAT(n, INSTANTIATE, type)
INSTANTIATE_N(4, Point)
Via Template Metaprogramming
See the solution and the very good explanation by phresnel below. This sounds like the preferable approach. Unfortunately explicit instantiation can only be used at the global level (a language limitation) and thus it cannot be used recursively. If the instantiation is done implicitely (see my previos question) then only those symbols are defined (and thus exported to the object file) that are actually used, i.e. you need to define each symbol of the class once (with a dummy).
This is not a very nice approach, but it avoids possibly nasty problem (and portability issues) of the preprocessor solutions.
Via Boost Preprocessor for multiple parameters.
Finally I also dived deeper into the Boost preprocessing library and tried to extend the result to create instantiations of the form
template class Node< int , 0 , 0 >;
template class Node< int , 1 , 0 >;
template class Node< int , 1 , 1 >;
template class Node< int , 2 , 0 >;
template class Node< int , 2 , 1 >;
template class Node< int , 2 , 2 >;
template class Node< float , 0 , 0 >;
template class Node< float , 1 , 0 >;
template class Node< float , 1 , 1 >;
template class Node< float , 2 , 0 >;
template class Node< float , 2 , 1 >;
template class Node< float , 2 , 2 >;
So a template Node<Scalar, pdim, ldim>
with Scalar
and arithmetic type pdim
and integer and ldim <= pdim
another integer.
I only was able to extend the approach using BOOST_PP_REPEAT
for templates with two arguments as BOOST_PP_REPEAT
can currently be only nested 3 levels deep. Two level for the template parameters and one level for BOOST_PP_ENUM
was the maximum I could achieve with this technique. It is more flexible to use the file iteration technique which supports up to 5 levels.
This code I was able to generate with the code
#define INTTOTYPE0 (int, (float, (double, _)))
#define NUM_TEMPLATE_ARGS 3
#define MAX_TEMPLATE_PARAM0 2
#define MAX_TEMPLATE_PARAM1(i0) 2
#define MAX_TEMPLATE_PARAM2(i0, i1) i1
#define CLASSNAME Node
#include "util/templateRecInstant.h"
the four instantiations for the Point class in the question can be generated via
#define NUM_TEMPLATE_ARGS 1
#define MAX_TEMPLATE_PARAM0 3
#define CLASSNAME Point
#include "util/templateRecInstant.h"
Both methods are achieved with the file "util/templateRecInstant.h" with the contents
#if !BOOST_PP_IS_ITERATING
#define MY_FILE "util/templateRecInstant.h"
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/list/at.hpp>
#ifndef NUM_TEMPLATE_ARGS
#error need to define NUM_TEMPLATE_ARGS
#endif
#ifndef MAX_TEMPLATE_PARAM0
#error need to specify MAX_TEMPLATE_PARAM0, MAX_TEMPLATE_PARAM1, ..., up tp NUM_TEMPLATE_ARGS
#endif
#ifndef DEFAULT_INTTOTYPE
#define DEFAULT_INTTOTYPE (0, (1, (2, (3, (4, (5, (6, (7, (8, (9, _))))))))))
#endif
#ifndef INTTOTYPE0
#define INTTOTYPE0 DEFAULT_INTTOTYPE
#endif
#ifndef INTTOTYPE1
#define INTTOTYPE1 DEFAULT_INTTOTYPE
#endif
#ifndef INTTOTYPE2
#define INTTOTYPE2 DEFAULT_INTTOTYPE
#endif
#ifndef INTTOTYPE3
#define INTTOTYPE3 DEFAULT_INTTOTYPE
#endif
#if NUM_TEMPLATE_ARGS > 0
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, \
MAX_TEMPLATE_PARAM0, MY_FILE ))
#include BOOST_PP_ITERATE()
#endif
#if NUM_TEMPLATE_ARGS == 0
template class CLASSNAME< \
>;
#endif
#undef MY_FILE
#undef NUM_TEMPLATE_ARGS
#undef CLASSNAME
#undef MAX_TEMPLATE_PARAM0
#undef MAX_TEMPLATE_PARAM1
#undef MAX_TEMPLATE_PARAM2
#undef MAX_TEMPLATE_PARAM3
#undef INTTOTYPE0
#undef INTTOTYPE1
#undef INTTOTYPE2
#undef INTTOTYPE3
#elif BOOST_PP_ITERATION_DEPTH() == 1
#if NUM_TEMPLATE_ARGS > 1
#define BOOST_PP_ITERATION_PARAMS_2 (3, (0, \
MAX_TEMPLATE_PARAM1(BOOST_PP_FRAME_ITERATION(1)), \
MY_FILE))
#include BOOST_PP_ITERATE()
#endif
#if NUM_TEMPLATE_ARGS == 1
template class CLASSNAME< \
BOOST_PP_LIST_AT( INTTOTYPE0, BOOST_PP_FRAME_ITERATION(1)) \
>;
#endif
#elif BOOST_PP_ITERATION_DEPTH() == 2
#if NUM_TEMPLATE_ARGS > 2
#define BOOST_PP_ITERATION_PARAMS_3 (3, (0, \
MAX_TEMPLATE_PARAM2(BOOST_PP_FRAME_ITERATION(1) \
, BOOST_PP_FRAME_ITERATION(2) \
), \
MY_FILE))
#include BOOST_PP_ITERATE()
#endif
#if NUM_TEMPLATE_ARGS == 2
template class CLASSNAME< \
BOOST_PP_LIST_AT( INTTOTYPE0, BOOST_PP_FRAME_ITERATION(1)) \
, BOOST_PP_LIST_AT( INTTOTYPE1, BOOST_PP_FRAME_ITERATION(2)) \
>;
#endif
#elif BOOST_PP_ITERATION_DEPTH() == 3
#if NUM_TEMPLATE_ARGS > 3
#define BOOST_PP_ITERATION_PARAMS_4 (3, (0, \
MAX_TEMPLATE_PARAM3(BOOST_PP_FRAME_ITERATION(1) \
, BOOST_PP_FRAME_ITERATION(2) \
, BOOST_PP_FRAME_ITERATION(3) \
), \
MY_FILE))
#include BOOST_PP_ITERATE()
#endif
#if NUM_TEMPLATE_ARGS == 3
template class CLASSNAME< \
BOOST_PP_LIST_AT( INTTOTYPE0, BOOST_PP_FRAME_ITERATION(1)) \
, BOOST_PP_LIST_AT( INTTOTYPE1, BOOST_PP_FRAME_ITERATION(2)) \
, BOOST_PP_LIST_AT( INTTOTYPE2, BOOST_PP_FRAME_ITERATION(3)) \
>;
#endif
#elif BOOST_PP_ITERATION_DEPTH() == 4
#if NUM_TEMPLATE_ARGS == 4
template class CLASSNAME< \
BOOST_PP_LIST_AT( INTTOTYPE0, BOOST_PP_FRAME_ITERATION(1)) \
, BOOST_PP_LIST_AT( INTTOTYPE1, BOOST_PP_FRAME_ITERATION(2)) \
, BOOST_PP_LIST_AT( INTTOTYPE2, BOOST_PP_FRAME_ITERATION(3)) \
, BOOST_PP_LIST_AT( INTTOTYPE3, BOOST_PP_FRAME_ITERATION(4)) \
>;
#endif
#if NUM_TEMPLATE_ARGS > 4
#error "NUM_TEMPLATE_ARGS > 4 is not supported (limitation by boost)"
#endif
#endif
If you stumble upon this problem, feel free to use the above code. To generate this code I used 1 as a reference.
template class Point<0>;
works perfectly fine, just the recursive explicit instantiation, via template meta-programming (see the above linked post) this did not export symbols in the object file. – Anthony