Обзор решений
Посредством ускоренного препроцессора (BOOST_PP_REPEAT)
См. Решение, предложенное Люком Турайем
#define INSTANTIATE(_, n, type) template class type<n>;
#define INSTANTIATE_N(n, type) BOOST_PP_REPEAT(n, INSTANTIATE, type)
INSTANTIATE_N(4, Point)
Через шаблонное метапрограммирование
Смотрите решение и очень хорошее объяснение по phresnel ниже.Это звучит как предпочтительный подход.К сожалению, явная реализация может использоваться только на глобальном уровне (ограничение языка) и, следовательно, не может использоваться рекурсивно.Если создание экземпляра выполняется неявно (см. Мой предыдущий вопрос), то определяются только те символы (и, следовательно, экспортируемые в объектный файл), которые фактически используются, т. Е. Вам необходимо определить каждый символ класса один раз (с помощью фиктивного элемента).
Это не очень хороший подход, но он позволяет избежать, возможно, неприятных проблем (и проблем с переносимостью) решений препроцессора.
Через препроцессор Boost для нескольких параметров.
Наконец-то ятакже углубился в библиотеку предварительной обработки Boost и попытался расширить результат для создания экземпляров вида
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 >;
Таким образом, шаблон Node<Scalar, pdim, ldim>
с Scalar
и арифметическим типом pdim
и целыми числами и ldim <= pdim
другое целое число.
Мне удалось расширить подход только с использованием BOOST_PP_REPEAT
для шаблонов с двумя аргументами, поскольку BOOST_PP_REPEAT
в настоящее время может иметь только вложенную глубину 3 уровня.Два уровня для параметров шаблона и один уровень для BOOST_PP_ENUM
- это максимум, которого я мог достичь с помощью этой техники.Более гибко использовать технику итерации файла , которая поддерживает до 5 уровней.
Этот код, который мне удалось сгенерировать с помощью кода
#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"
из четырехэкземпляры для класса Point в вопросе могут быть сгенерированы с помощью
#define NUM_TEMPLATE_ARGS 1
#define MAX_TEMPLATE_PARAM0 3
#define CLASSNAME Point
#include "util/templateRecInstant.h"
Оба метода выполняются с помощью файла "util / templateRecInstant.h" с содержанием
#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
Если вы оступилисьпо этой проблеме, не стесняйтесь использовать приведенный выше код.Для генерации этого кода я использовал 1 в качестве ссылки.