ローカルイテレーション

ローカルイテレーションは単純な垂直反復を構成するものである。 それはマクロをユーザが指定した範囲の整数の値を付けてマクロを展開する。 それぞれの展開されたものは別々の行となる。

チュートリアル

このメカニズムは動作させるのに二つの情報を必要とする。 どの範囲をイテレートするかという情報と、展開させるべきマクロである。 この情報は二つの名前付き外部引数を通じて取得される。 これらの引数はBOOST_PP_LOCAL_LIMITSBOOST_PP_LOCAL_MACROというユーザ定義のマクロによって指定される。
BOOST_PP_LOCAL_LIMITSはイテレートする範囲を指定する。 それは下限と上限をあらわす二つの要素を含む組へと展開されなければならない。 上限と下限はともに0からBOOST_PP_LIMIT_ITERATIONの範囲内の値でなければならない。 例えば、もしユーザが0から10までの範囲でマクロを展開したいと望むなら、 BOOST_PP_LOCAL_LIMITSは次のようになる:
#define BOOST_PP_LOCAL_LIMITS (0, 10)
マクロの名前の直後に空白があることに注意せよ。 このマクロは二つの引数を取らない。 上の例では、もし空白がなければ、010は不正な識別子であるとしてプリプロセッサがエラーを返す。
BOOST_PP_LOCAL_LIMITSマクロで指定される上限と下限はともに評価されるパラメータである。 したがってそれらは単純な算術的あるいは論理的な式でもよい。 たとえば、上の定義は次のようにも書ける:
#define N() 5
#define BOOST_PP_LOCAL_LIMITS (0, N() + 5)
このために、もしマクロの後ろの空白が無ければ、この定義は文法的に不正なものになってしまうことがありうる:
#define A 0
#define B 10
#define BOOST_PP_LOCAL_LIMITS(A, B)
   // 注意:       空白が無い ^
もしこれが起これば、このマクロを利用するメカニズムの内側でエラーが起こるだろう。 (その場合の)エラーメッセージは意味不明のものとなるかもしれないので、常に空白をいれることを忘れてはならない。 上の例の正しいバージョンは次のようになる:
#define A 0
#define B 10
#define BOOST_PP_LOCAL_LIMITS (A, B)
   // 注意:      空白が有る  ^
BOOST_PP_LOCAL_MACROはこのメカニズムによって展開されるマクロである。 このマクロはイテレーションの各値について展開される。 それは一つの引数を取るマクロであるか、あるいは結果的に一つの引数を付けて呼べるようになるものでなければならない:
#define BOOST_PP_LOCAL_MACRO(n) \
   template<> struct sample<n> { }; \
   /**/
...または...
#define SAMPLE(n) \
   template<> struct sample<n> { }; \
   /**/

#define BOOST_PP_LOCAL_MACRO SAMPLE
これら二つのマクロが定義されたなら、ローカルイテレーションはBOOST_PP_LOCAL_ITERATE()をincludeすることによって起動する。 Once these two macros are defined, the local iteration is initiated by including BOOST_PP_LOCAL_ITERATE().
??=include BOOST_PP_LOCAL_ITERATE()
(トークン??=は、#へと置換されるトライグラフである。 私はマクロの定義や展開するのではなくincludeするのであることをはっきりさせるためにトライグラフを使ったが、別にそれは必須ではない。 ダイグラフ%:も使うことができる。 いくつかのコンパイラはトライグラフやダイグラフを受け付けないことを憶えていてほしい。 その場合以外では、好きなものを使ってよい。)
テンプレートクラスsampleの特別バージョン生成を繰り返すには、次のようなものを組み合わせればよい.... In order to repeat the sample specialization, the pieces must be put together....
#define BOOST_PP_LOCAL_MACRO(n) \
   template<> struct sample<n> { }; \
   /**/

#define BOOST_PP_LOCAL_LIMITS (0, 10)
??=include BOOST_PP_LOCAL_ITERATE()
これはsampleの特別バージョン生成を、0から10の範囲で繰り返すことになる。 出力は次のようになるだろう:
template<> struct sample<0> { };
template<> struct sample<1> { };
template<> struct sample<2> { };

// ...

template<> struct sample<10> { };
ローカルイテレーションが完了したら、BOOST_PP_LOCAL_LIMITSBOOST_PP_LOCAL_MACROは自動的にundefされる。 もしそれらの値をローカルイテレーション使用後も必要とするならば、それらを間接的に定義しなければならない:
#define LIMITS (0, 10)

#define SAMPLE(n) \
   template<> struct sample<n> { }; \
   /**/

#define BOOST_PP_LOCAL_LIMITS LIMITS
#define BOOST_PP_LOCAL_MACRO(n) SAMPLE(n)

??=include BOOST_PP_LOCAL_ITERATE()

参照

- Paul Mensonides