open-mgl-dev (開発バージョン) (0.7.9.80) | 2009-11-02 22:25 |
open-mgl (DirectX9, VC++2008) (0.7.9) | 2009-09-27 20:32 |
roast-dev (開発バージョン) (0.0.1.40-dev) | 2009-11-02 23:09 |
プリプロセッサを活用して繰り返し展開を行います。主にメタプログラミングなどに活用できます。
#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))
でも上手く行くんじゃないか?と
これならば問題なくコンパイルが通るようになります。