FrontPageMSLMSL/PP

msl_pp_repeat

プリプロセッサを活用して繰り返し展開を行います。主にメタプログラミングなどに活用できます。

MSL_PP_REPEART_INC

#define MY_CALLBACK(n) if( hoge##n == 0 )return false;
MSL_PP_REPEART_INC(5,MY_CALLBACK)

if( hoge1 == 0 )return false;
if( hoge2 == 0 )return false;
if( hoge3 == 0 )return false;
if( hoge4 == 0 )return false;
if( hoge5 == 0 )return false;
#define LOOP_NEST_CALLBACK1(n) for(int i##n=0; i##n<LOOP_MAX; i##n++) {
#define LOOP_NEST_CALLBACK2(n) }

#define LOOP_MAX (4)
int count=0;
MSL_PP_REPEART_INC(4,LOOP_NEST_CALLBACK1)
printf("%d, %d, %d, %d\n", i1, i2, i3, i4);
MSL_PP_REPEART_INC(4,LOOP_NEST_CALLBACK2)

for(int i1; i1<LOOP_MAX; i1++) {
for(int i2; i2<LOOP_MAX; i2++) {
for(int i3; i3<LOOP_MAX; i3++) {
for(int i4; i4<LOOP_MAX; i4++) {
printf("%d, %d, %d, %d\n", i1, i2, i3, i4);
}
}
}
}
0, 0, 0, 0
0, 0, 0, 1
0, 0, 0, 2
0, 0, 0, 3
0, 0, 1, 0
0, 0, 1, 1
0, 0, 1, 2
0, 0, 1, 3
 :
 :
3, 3, 2, 0
3, 3, 2, 1
3, 3, 2, 2
3, 3, 2, 3
3, 3, 3, 0
3, 3, 3, 1
3, 3, 3, 2
3, 3, 3, 3

コールバック引数の値を任意の数値から始めたい

MSL_PP_INC()、MSL_PP_DEC()、MSL_PP_ADD()、MSL_PP_SUB() 等のマクロを利用する事により、
これに対し対処が可能です。

同様に、2,4,6,8...のようにしたい場合には MSL_PP_MUL() を活用出来ます。


気をつけるべき事

うっかりやってしまう事として。

#define HOGE_CALLBACK(n) int hoge ##MSL_PP_INC(n)

のような書き方があります。多くの人は「一体何が問題なのか?」と思われるでしょう。

私も、最初のうちは知らなかったのですが、##演算子は単なる文字列の連結ではない、と言うことです。

##演算子は、単なる連結ではなく、##の後に来る文字列が、マクロとして与えられたパラメータである必要があります。
やってみると分かるのですが、#defineでない部分でいきなり「int hoge##2」のような記述をしても、これはコンパイルエラーになります。

先の例を見てみると、##の後に来ている「MSL_PP_INC(n)」は、nこそマクロのパラメータでありますが、
MSL_PP_INCはマクロのパラメータではありません。よってこれは上手く展開されず、コンパイルエラーとなります。


これを回避するには、以下のようにします。

#define HOGE_CALLBACK__(n) int hoge##n
#define HOGE_CALLBACK_(n) HOGE_CALLBACK__(n)
#define HOGE_CALLBACK(n) HOGE_CALLBACK_(MSL_PP_INC(n))

#define HOGE_CALLBACK_(n) int hoge##n
#define HOGE_CALLBACK(n) HOGE_CALLBACK_(MSL_PP_INC(n))

でも上手く行くんじゃないか?と

これならば問題なくコンパイルが通るようになります。