ソリューションの調査
ブースト プリプロセッサ経由 (BOOST_PP_REPEAT)
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)
テンプレート メタプログラミング経由
以下のphresnelによる解決策と非常に良い説明を参照してください。これは好ましいアプローチのように思えます。残念ながら、明示的なインスタンス化はグローバル レベル (言語の制限) でしか使用できないため、再帰的に使用することはできません。インスタンス化が暗黙的に行われる場合 (前の質問を参照)、実際に使用されるシンボルのみが定義されます (したがって、オブジェクト ファイルにエクスポートされます)。つまり、クラスの各シンボルを一度 (ダミーで) 定義する必要があります。
これはあまり良い方法ではありませんが、プリプロセッサ ソリューションの厄介な問題 (および移植性の問題) を回避できます。
複数のパラメータの Boost Preprocessor 経由。
最後に、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
現在、3 レベルの深さしかネストできないBOOST_PP_REPEAT
ため、2 つの引数を持つテンプレートを使用してアプローチを拡張することしかできませんでした。BOOST_PP_REPEAT
テンプレート パラメータの 2 つのレベルと 1 つのレベル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 クラスの 4 つのインスタンス化は、次の方法で生成できます。
#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を使用しました。