C++ プリプロセッサメタプログラミングの基礎
置換の基本
関数形式のマクロに渡されたものはなんでもその通りに置換されます
#define FOO( p ) p
FOO( 1 ) ↓ //p → 1 1
FOO( "aaa" ) ↓ //p → "aaa" "aaa"
FOO( bbb ) ↓ //p → bbb bbb
渡されたものがマクロであればさらにそれも置換されます
#define FOO( p ) p #define aaa 1
FOO( aaa ) ↓ //p → aaa aaa ↓ //aaa → 1 1
ただし、マクロの定義に文字列化演算子 # や連結演算子 ## が含まれているときは置換処理はそこで停止します
#define FOO( p ) #p #define aaa 1
FOO( aaa ) ↓ //p → aaa #aaa ↓ "aaa"
#define FOO( p ) bbb ## p #define aaa 1
FOO( aaa ) ↓ //p → aaa bbb ## aaa ↓ bbbaaa
文字列化や連結をしつつ置換もしたいという場合には、関数形式のマクロの実装を多段階にします
#define FOO_( p ) bbb ## p #define FOO( p ) FOO_( p ) #define aaa 1
FOO( aaa ) ↓ //p → aaa FOO_( aaa ) ↓ //aaa → 1 FOO_( 1 ) ↓ //p → 1 bbb ## 1 ↓ bbb1
#define FOO_( p ) bbb ## p #define FOO( p ) FOO_( p ) #define aaa 1 #define bbb1 10
FOO( aaa ) ↓ //p → aaa FOO_( aaa ) ↓ //aaa → 1 FOO_( 1 ) ↓ //p → 1 bbb ## 1 ↓ bbb1 ↓ 10
毎回多段階にするのも面倒なので下記のようなマクロを用意してもいいでしょう
#define PP_STR_( s ) #s #define PP_STR( s ) PP_STR_( s ) #define PP_CONCAT_( lhs, rhs ) lhs ## rhs #define PP_CONCAT( lhs, rhs ) PP_CONCAT_( lhs, rhs )
この辺りの規則については標準では次の辺りで規定されています
16 Preprocessing directives 16.3 Macro replacement 16.3.1 Argument substitution
条件分岐
連結を使って呼び出すマクロの名前を変えてあげると条件分岐を実現できます
#define PP_IF_0( then_, else_ ) else_ #define PP_IF_1( then_, else_ ) then_ #define PP_IF( cond, then_, else_ ) PP_CONCAT(PP_IF_,cond)( then_, else_ ) #define aaa 0 #define bbb 2 #define ccc 3
PP_IF( aaa, bbb, ccc ) ↓ // cond → aaa, then_ → bbb, else_ → ccc PP_CONCAT(PP_IF_,aaa)( bbb, ccc ) ↓ // aaa → 0, bbb → 2, ccc → 3 PP_CONCAT(PP_IF_,0)( 2, 3 ) ↓ // lhs → PP_IF_, rhs → 0 PP_CONCAT_(PP_IF_,0)( 2, 3 ) ↓ // lhs → PP_IF_, rhs → 0 PP_IF_##0( 2, 3 ) ↓ PP_IF_0( 2, 3 ) ↓ // then_ → 2, else_ → 3 3
連結を別のマクロで解決せず定義を多段にしても同じです
#define PP_IF_0( then_, else_ ) else_ #define PP_IF_1( then_, else_ ) then_ #define PP_IF_( cond, then_, else_ ) PP_IF_##cond( then_, else_ ) #define PP_IF( cond, then_, else_ ) PP_IF_( cond, then_, else_ )
条件分岐ができるとだいたいのことはできるようになります
ただ、このままでは cond に 0 1 以外のものが渡されると機能しません
0 以外の値はいくつであっても 1 に置換するというようなことは実現できるでしょうか
数値の二値化
数値を 0 か 1 にするのに一番簡単な方法は次のように必要なすべての値用のマクロを予め用意しておくことです
#define PP_BOOL_0 0 #define PP_BOOL_1 1 #define PP_BOOL_2 1 #define PP_BOOL_3 1 #define PP_BOOL_4 1 #define PP_BOOL_5 1 #define PP_BOOL_6 1 #define PP_BOOL_7 1 #define PP_BOOL_8 1 #define PP_BOOL_9 1 #define PP_BOOL_10 1 #define PP_BOOL_11 1 #define PP_BOOL_12 1 #define PP_BOOL_13 1 #define PP_BOOL_14 1 #define PP_BOOL_15 1 . . . #define PP_BOOL( value ) PP_CONCAT( PP_BOOL_, value )
使用例
#define aaa 10 PP_BOOL( aaa ) ↓ // value → aaa PP_CONCAT( PP_BOOL_, aaa ) ↓ // aaa → 10 PP_CONCAT( PP_BOOL_, 10 ) ↓ // lhs → PP_BOOL_, rhs → 10 PP_CONCAT_( PP_BOOL_, 10 ) ↓ // lhs → PP_BOOL_, rhs → 10 PP_BOOL_##10 ↓ PP_BOOL_10 ↓ 1
これを上記の条件分岐に適用すると次のようになります
#define PP_IF_0( then_, else_ ) else_ #define PP_IF_1( then_, else_ ) then_ #define PP_IF( cond, then_, else_ ) PP_CONCAT(PP_IF_,PP_BOOL(cond))( then_, else_ ) #define aaa 10 #define bbb 2 #define ccc 3
PP_IF( aaa, bbb, ccc ) ↓ // cond → aaa, then_ → bbb, else_ → ccc PP_CONCAT(PP_IF_,PP_BOOL(aaa))( bbb, ccc ) ↓ // aaa → 10, bbb → 2, ccc → 3 PP_CONCAT(PP_IF_,PP_BOOL(10))( 2, 3 ) ↓ // value → 10 PP_CONCAT(PP_IF_,PP_CONCAT(PP_BOOL_,10))( 2, 3 ) ↓ // lhs → PP_BOOL_, rhs → 10 PP_CONCAT(PP_IF_,PP_CONCAT_(PP_BOOL_,10))( 2, 3 ) ↓ // lhs → PP_BOOL_, rhs → 10 PP_CONCAT(PP_IF_,PP_BOOL_##10)( 2, 3 ) ↓ PP_CONCAT(PP_IF_,PP_BOOL_10)( 2, 3 ) ↓ // PP_BOOL_10 → 1 PP_CONCAT(PP_IF_,1)( 2, 3 ) ↓ // lhs → PP_IF_, rhs → 1 PP_CONCAT_(PP_IF_,1)( 2, 3 ) ↓ // lhs → PP_IF_, rhs → 1 PP_IF_##1( 2, 3 ) ↓ PP_IF_1( 2, 3 ) ↓ // then_ → 2, else_ → 3 2
数値の更新
マクロの再定義はできないので次のようなことはできません
#define PP_COUNTER 0 #define PP_COUNTER (PP_COUNTER+1) // エラー
また再帰もできないので次のようなこともできません
#define PP_COUNTER 0 #define PP_COUNTER_TEMP1 (PP_COUNTER+1) #undef PP_COUNTER #define PP_COUNTER PP_COUNTER_TEMP1
PP_COUNTER ↓ PP_COUNTER_TEMP1 ↓ (PP_COUNTER+1) // マクロではない PP_COUNTER という名前の変数を参照
ただ実現できないわけではありません
基本的には上記のように一度別のマクロに値を入れてそれを戻すという方法で実現できます
上記の PP_COUNTER_TEMP1 の問題はその実装で直接 PP_COUNTER を参照しているために結局再帰になってしまっていたというところにありました
二重定義や再帰にならないように気を付ければマクロの値を更新することもできます
次のように計算結果と同じ値の別のマクロを定義します
- PP_COUNTER_TEMP1 に計算結果を入れる
#define PP_COUNTER 0 #define PP_COUNTER_TEMP1 (PP_COUNTER+1)
- PP_COUNTER_TEMP1 と全く同じ値の PP_COUNTER_TEMP2 を作る
このとき PP_COUNTER_TEMP2 の定義には PP_COUNTER_TEMP1 や PP_COUNTER を使わない
必要なだけすべての値用のマクロを用意する#if PP_COUNTER_TEMP1 == 0 #define PP_COUNTER_TEMP2 0 #elif PP_COUNTER_TEMP1 == 1 #define PP_COUNTER_TEMP2 1 #elif PP_COUNTER_TEMP1 == 2 #define PP_COUNTER_TEMP2 2 #elif PP_COUNTER_TEMP1 == 3 #define PP_COUNTER_TEMP2 3 #elif PP_COUNTER_TEMP1 == 4 #define PP_COUNTER_TEMP2 4 #elif PP_COUNTER_TEMP1 == 5 #define PP_COUNTER_TEMP2 5 #elif PP_COUNTER_TEMP1 == 6 #define PP_COUNTER_TEMP2 6 #elif PP_COUNTER_TEMP1 == 7 #define PP_COUNTER_TEMP2 7 #elif PP_COUNTER_TEMP1 == 8 #define PP_COUNTER_TEMP2 8 #elif PP_COUNTER_TEMP1 == 9 #define PP_COUNTER_TEMP2 9 #elif PP_COUNTER_TEMP1 == 10 #define PP_COUNTER_TEMP2 10 #elif PP_COUNTER_TEMP1 == 11 #define PP_COUNTER_TEMP2 11 #elif PP_COUNTER_TEMP1 == 12 #define PP_COUNTER_TEMP2 12 #elif PP_COUNTER_TEMP1 == 13 #define PP_COUNTER_TEMP2 13 #elif PP_COUNTER_TEMP1 == 14 #define PP_COUNTER_TEMP2 14 #elif PP_COUNTER_TEMP1 == 15 #define PP_COUNTER_TEMP2 15 . . . #else #error unexpected: PP_COUNTER_TEMP1 #endif #undef PP_COUNTER_TEMP1
- PP_COUNTER_TEMP2 を PP_COUNTER に戻す
PP_COUNTER_TEMP2 の定義は即値にしてあるので PP_COUNTER は関係していません
ですからこのように PP_COUNTER を更新しても再帰にならず望みの結果を得ることができます#undef PP_COUNTER #define PP_COUNTER PP_COUNTER_TEMP2
ただこのように必要な数だけマクロを用意するのも大変です
数値の分解と結合
数値を十進数の各桁に分けて処理するようにすると各桁は10個の処理をするだけでよくなりますから少しは楽になります
// 6桁分の実装 #define PP_DIGIT0( value ) ((value)%10) #define PP_DIGIT1( value ) (((value)/10)%10) #define PP_DIGIT2( value ) (((value)/100)%10) #define PP_DIGIT3( value ) (((value)/1000)%10) #define PP_DIGIT4( value ) (((value)/10000)%10) #define PP_DIGIT5( value ) (((value)/100000)%10) #define PP_MAKE_INT_0( _5, _4, _3, _2, _1, _0 ) _0 #define PP_MAKE_INT_1( _5, _4, _3, _2, _1, _0 ) _1 ## _0 #define PP_MAKE_INT_2( _5, _4, _3, _2, _1, _0 ) _2 ## _1 ## _0 #define PP_MAKE_INT_3( _5, _4, _3, _2, _1, _0 ) _3 ## _2 ## _1 ## _0 #define PP_MAKE_INT_4( _5, _4, _3, _2, _1, _0 ) _4 ## _3 ## _2 ## _1 ## _0 #define PP_MAKE_INT_5( _5, _4, _3, _2, _1, _0 ) _5 ## _4 ## _3 ## _2 ## _1 ## _0 #define PP_MAKE_INT0 PP_MAKE_INT_0 #define PP_MAKE_INT1( _5, _4, _3, _2, _1, _0 ) PP_IF(_1,PP_MAKE_INT_1,PP_MAKE_INT0)( _5, _4, _3, _2, _1, _0 ) #define PP_MAKE_INT2( _5, _4, _3, _2, _1, _0 ) PP_IF(_2,PP_MAKE_INT_2,PP_MAKE_INT1)( _5, _4, _3, _2, _1, _0 ) #define PP_MAKE_INT3( _5, _4, _3, _2, _1, _0 ) PP_IF(_3,PP_MAKE_INT_3,PP_MAKE_INT2)( _5, _4, _3, _2, _1, _0 ) #define PP_MAKE_INT4( _5, _4, _3, _2, _1, _0 ) PP_IF(_4,PP_MAKE_INT_4,PP_MAKE_INT3)( _5, _4, _3, _2, _1, _0 ) #define PP_MAKE_INT( _5, _4, _3, _2, _1, _0 ) PP_IF(_5,PP_MAKE_INT_5,PP_MAKE_INT4)( _5, _4, _3, _2, _1, _0 )
これを使って上記の数値の更新処理を書き直してみると次のようになります
pp_counter_inc.inl
#define PP_COUNTER 12345 #define PP_COUNTER_TEMP1 (PP_COUNTER+1) #define PP_COUNTER_TEMP1_DIGIT0 PP_DIGIT0(PP_COUNTER_TEMP1) #define PP_COUNTER_TEMP1_DIGIT1 PP_DIGIT1(PP_COUNTER_TEMP1) #define PP_COUNTER_TEMP1_DIGIT2 PP_DIGIT2(PP_COUNTER_TEMP1) #define PP_COUNTER_TEMP1_DIGIT3 PP_DIGIT3(PP_COUNTER_TEMP1) #define PP_COUNTER_TEMP1_DIGIT4 PP_DIGIT4(PP_COUNTER_TEMP1) #define PP_COUNTER_TEMP1_DIGIT5 PP_DIGIT5(PP_COUNTER_TEMP1) #undef PP_COUNTER_TEMP2_DIGIT0 #if PP_COUNTER_TEMP1_DIGIT0 == 0 #define PP_COUNTER_TEMP2_DIGIT0 0 #elif PP_COUNTER_TEMP1_DIGIT0 == 1 #define PP_COUNTER_TEMP2_DIGIT0 1 #elif PP_COUNTER_TEMP1_DIGIT0 == 2 #define PP_COUNTER_TEMP2_DIGIT0 2 #elif PP_COUNTER_TEMP1_DIGIT0 == 3 #define PP_COUNTER_TEMP2_DIGIT0 3 #elif PP_COUNTER_TEMP1_DIGIT0 == 4 #define PP_COUNTER_TEMP2_DIGIT0 4 #elif PP_COUNTER_TEMP1_DIGIT0 == 5 #define PP_COUNTER_TEMP2_DIGIT0 5 #elif PP_COUNTER_TEMP1_DIGIT0 == 6 #define PP_COUNTER_TEMP2_DIGIT0 6 #elif PP_COUNTER_TEMP1_DIGIT0 == 7 #define PP_COUNTER_TEMP2_DIGIT0 7 #elif PP_COUNTER_TEMP1_DIGIT0 == 8 #define PP_COUNTER_TEMP2_DIGIT0 8 #elif PP_COUNTER_TEMP1_DIGIT0 == 9 #define PP_COUNTER_TEMP2_DIGIT0 9 #endif // PP_COUNTER_TEMP1_DIGIT0 #undef PP_COUNTER_TEMP2_DIGIT1 #if PP_COUNTER_TEMP1_DIGIT1 == 0 #define PP_COUNTER_TEMP2_DIGIT1 0 #elif PP_COUNTER_TEMP1_DIGIT1 == 1 #define PP_COUNTER_TEMP2_DIGIT1 1 #elif PP_COUNTER_TEMP1_DIGIT1 == 2 #define PP_COUNTER_TEMP2_DIGIT1 2 #elif PP_COUNTER_TEMP1_DIGIT1 == 3 #define PP_COUNTER_TEMP2_DIGIT1 3 #elif PP_COUNTER_TEMP1_DIGIT1 == 4 #define PP_COUNTER_TEMP2_DIGIT1 4 #elif PP_COUNTER_TEMP1_DIGIT1 == 5 #define PP_COUNTER_TEMP2_DIGIT1 5 #elif PP_COUNTER_TEMP1_DIGIT1 == 6 #define PP_COUNTER_TEMP2_DIGIT1 6 #elif PP_COUNTER_TEMP1_DIGIT1 == 7 #define PP_COUNTER_TEMP2_DIGIT1 7 #elif PP_COUNTER_TEMP1_DIGIT1 == 8 #define PP_COUNTER_TEMP2_DIGIT1 8 #elif PP_COUNTER_TEMP1_DIGIT1 == 9 #define PP_COUNTER_TEMP2_DIGIT1 9 #endif // PP_COUNTER_TEMP1_DIGIT1 #undef PP_COUNTER_TEMP2_DIGIT2 #if PP_COUNTER_TEMP1_DIGIT2 == 0 #define PP_COUNTER_TEMP2_DIGIT2 0 #elif PP_COUNTER_TEMP1_DIGIT2 == 1 #define PP_COUNTER_TEMP2_DIGIT2 1 #elif PP_COUNTER_TEMP1_DIGIT2 == 2 #define PP_COUNTER_TEMP2_DIGIT2 2 #elif PP_COUNTER_TEMP1_DIGIT2 == 3 #define PP_COUNTER_TEMP2_DIGIT2 3 #elif PP_COUNTER_TEMP1_DIGIT2 == 4 #define PP_COUNTER_TEMP2_DIGIT2 4 #elif PP_COUNTER_TEMP1_DIGIT2 == 5 #define PP_COUNTER_TEMP2_DIGIT2 5 #elif PP_COUNTER_TEMP1_DIGIT2 == 6 #define PP_COUNTER_TEMP2_DIGIT2 6 #elif PP_COUNTER_TEMP1_DIGIT2 == 7 #define PP_COUNTER_TEMP2_DIGIT2 7 #elif PP_COUNTER_TEMP1_DIGIT2 == 8 #define PP_COUNTER_TEMP2_DIGIT2 8 #elif PP_COUNTER_TEMP1_DIGIT2 == 9 #define PP_COUNTER_TEMP2_DIGIT2 9 #endif // PP_COUNTER_TEMP1_DIGIT2 #undef PP_COUNTER_TEMP2_DIGIT3 #if PP_COUNTER_TEMP1_DIGIT3 == 0 #define PP_COUNTER_TEMP2_DIGIT3 0 #elif PP_COUNTER_TEMP1_DIGIT3 == 1 #define PP_COUNTER_TEMP2_DIGIT3 1 #elif PP_COUNTER_TEMP1_DIGIT3 == 2 #define PP_COUNTER_TEMP2_DIGIT3 2 #elif PP_COUNTER_TEMP1_DIGIT3 == 3 #define PP_COUNTER_TEMP2_DIGIT3 3 #elif PP_COUNTER_TEMP1_DIGIT3 == 4 #define PP_COUNTER_TEMP2_DIGIT3 4 #elif PP_COUNTER_TEMP1_DIGIT3 == 5 #define PP_COUNTER_TEMP2_DIGIT3 5 #elif PP_COUNTER_TEMP1_DIGIT3 == 6 #define PP_COUNTER_TEMP2_DIGIT3 6 #elif PP_COUNTER_TEMP1_DIGIT3 == 7 #define PP_COUNTER_TEMP2_DIGIT3 7 #elif PP_COUNTER_TEMP1_DIGIT3 == 8 #define PP_COUNTER_TEMP2_DIGIT3 8 #elif PP_COUNTER_TEMP1_DIGIT3 == 9 #define PP_COUNTER_TEMP2_DIGIT3 9 #endif // PP_COUNTER_TEMP1_DIGIT3 #undef PP_COUNTER_TEMP2_DIGIT4 #if PP_COUNTER_TEMP1_DIGIT4 == 0 #define PP_COUNTER_TEMP2_DIGIT4 0 #elif PP_COUNTER_TEMP1_DIGIT4 == 1 #define PP_COUNTER_TEMP2_DIGIT4 1 #elif PP_COUNTER_TEMP1_DIGIT4 == 2 #define PP_COUNTER_TEMP2_DIGIT4 2 #elif PP_COUNTER_TEMP1_DIGIT4 == 3 #define PP_COUNTER_TEMP2_DIGIT4 3 #elif PP_COUNTER_TEMP1_DIGIT4 == 4 #define PP_COUNTER_TEMP2_DIGIT4 4 #elif PP_COUNTER_TEMP1_DIGIT4 == 5 #define PP_COUNTER_TEMP2_DIGIT4 5 #elif PP_COUNTER_TEMP1_DIGIT4 == 6 #define PP_COUNTER_TEMP2_DIGIT4 6 #elif PP_COUNTER_TEMP1_DIGIT4 == 7 #define PP_COUNTER_TEMP2_DIGIT4 7 #elif PP_COUNTER_TEMP1_DIGIT4 == 8 #define PP_COUNTER_TEMP2_DIGIT4 8 #elif PP_COUNTER_TEMP1_DIGIT4 == 9 #define PP_COUNTER_TEMP2_DIGIT4 9 #endif // PP_COUNTER_TEMP1_DIGIT4 #undef PP_COUNTER_TEMP2_DIGIT5 #if PP_COUNTER_TEMP1_DIGIT5 == 0 #define PP_COUNTER_TEMP2_DIGIT5 0 #elif PP_COUNTER_TEMP1_DIGIT5 == 1 #define PP_COUNTER_TEMP2_DIGIT5 1 #elif PP_COUNTER_TEMP1_DIGIT5 == 2 #define PP_COUNTER_TEMP2_DIGIT5 2 #elif PP_COUNTER_TEMP1_DIGIT5 == 3 #define PP_COUNTER_TEMP2_DIGIT5 3 #elif PP_COUNTER_TEMP1_DIGIT5 == 4 #define PP_COUNTER_TEMP2_DIGIT5 4 #elif PP_COUNTER_TEMP1_DIGIT5 == 5 #define PP_COUNTER_TEMP2_DIGIT5 5 #elif PP_COUNTER_TEMP1_DIGIT5 == 6 #define PP_COUNTER_TEMP2_DIGIT5 6 #elif PP_COUNTER_TEMP1_DIGIT5 == 7 #define PP_COUNTER_TEMP2_DIGIT5 7 #elif PP_COUNTER_TEMP1_DIGIT5 == 8 #define PP_COUNTER_TEMP2_DIGIT5 8 #elif PP_COUNTER_TEMP1_DIGIT5 == 9 #define PP_COUNTER_TEMP2_DIGIT5 9 #endif // PP_COUNTER_TEMP1_DIGIT5 #undef PP_COUNTER_TEMP1 #undef PP_COUNTER_TEMP1_DIGIT0 #undef PP_COUNTER_TEMP1_DIGIT1 #undef PP_COUNTER_TEMP1_DIGIT2 #undef PP_COUNTER_TEMP1_DIGIT3 #undef PP_COUNTER_TEMP1_DIGIT4 #undef PP_COUNTER_TEMP1_DIGIT5 #undef PP_COUNTER_TEMP2 #define PP_COUNTER_TEMP2 PP_MAKE_INT(PP_COUNTER_TEMP2_DIGIT5,PP_COUNTER_TEMP2_DIGIT4,PP_COUNTER_TEMP2_DIGIT3,PP_COUNTER_TEMP2_DIGIT2,PP_COUNTER_TEMP2_DIGIT1,PP_COUNTER_TEMP2_DIGIT0) #undef PP_COUNTER #define PP_COUNTER PP_COUNTER_TEMP2
ここまででマクロの値を更新することができるようになったのですが、実はこのままだと二回目に同じことをしようとしたときにエラーになります
#define PP_COUNTER 0 #include "pp_counter_inc.inl" #include "pp_counter_inc.inl" // エラー
なぜでしょうか
正しい数値の更新
これは pp_counter_inc.inl の最後に PP_COUNTER_TEMP2_DIGIT0 などを #undef してみると PP_COUNTER_TEMP2 を解決できなくなってしまうことでわかると思います
新しい PP_COUNTER が最終的には PP_COUNTER_TEMP2_DIGIT0 などを使った実装に置き換わっているのが原因なのです
二度目に PP_COUNTER_TEMP1 から PP_COUNTER_TEMP2_DIGIT0 を作ろうとするときに PP_COUNTER_TEMP2_DIGIT0 を #undef します
しかし、今参照しようとしている PP_COUNTER_TEMP1 は最終的には PP_COUNTER_TEMP2_DIGIT0 に展開されるので、#undef されてしまうと解決できなくなってしまうのです
困りますね
困るので実は上記に加えてさらに処理が必要です
やるべきことは PP_COUNTER_TEMP2 から同じ値の PP_COUNTER_TEMP3 を作るということですが、これはマクロの名前が違うだけで PP_COUNTER_TEMP1 から PP_COUNTER_TEMP2 を作るのと全く同じ処理です
pp_counter_inc.inl
#define PP_COUNTER_TEMP1 (PP_COUNTER+1) #define PP_COUNTER_TEMP1_DIGIT0 PP_DIGIT0(PP_COUNTER_TEMP1) #define PP_COUNTER_TEMP1_DIGIT1 PP_DIGIT1(PP_COUNTER_TEMP1) #define PP_COUNTER_TEMP1_DIGIT2 PP_DIGIT2(PP_COUNTER_TEMP1) #define PP_COUNTER_TEMP1_DIGIT3 PP_DIGIT3(PP_COUNTER_TEMP1) #define PP_COUNTER_TEMP1_DIGIT4 PP_DIGIT4(PP_COUNTER_TEMP1) #define PP_COUNTER_TEMP1_DIGIT5 PP_DIGIT5(PP_COUNTER_TEMP1) #undef PP_COUNTER_TEMP2_DIGIT0 #if PP_COUNTER_TEMP1_DIGIT0 == 0 #define PP_COUNTER_TEMP2_DIGIT0 0 #elif PP_COUNTER_TEMP1_DIGIT0 == 1 #define PP_COUNTER_TEMP2_DIGIT0 1 #elif PP_COUNTER_TEMP1_DIGIT0 == 2 #define PP_COUNTER_TEMP2_DIGIT0 2 #elif PP_COUNTER_TEMP1_DIGIT0 == 3 #define PP_COUNTER_TEMP2_DIGIT0 3 #elif PP_COUNTER_TEMP1_DIGIT0 == 4 #define PP_COUNTER_TEMP2_DIGIT0 4 #elif PP_COUNTER_TEMP1_DIGIT0 == 5 #define PP_COUNTER_TEMP2_DIGIT0 5 #elif PP_COUNTER_TEMP1_DIGIT0 == 6 #define PP_COUNTER_TEMP2_DIGIT0 6 #elif PP_COUNTER_TEMP1_DIGIT0 == 7 #define PP_COUNTER_TEMP2_DIGIT0 7 #elif PP_COUNTER_TEMP1_DIGIT0 == 8 #define PP_COUNTER_TEMP2_DIGIT0 8 #elif PP_COUNTER_TEMP1_DIGIT0 == 9 #define PP_COUNTER_TEMP2_DIGIT0 9 #endif // PP_COUNTER_TEMP1_DIGIT0 #undef PP_COUNTER_TEMP2_DIGIT1 #if PP_COUNTER_TEMP1_DIGIT1 == 0 #define PP_COUNTER_TEMP2_DIGIT1 0 #elif PP_COUNTER_TEMP1_DIGIT1 == 1 #define PP_COUNTER_TEMP2_DIGIT1 1 #elif PP_COUNTER_TEMP1_DIGIT1 == 2 #define PP_COUNTER_TEMP2_DIGIT1 2 #elif PP_COUNTER_TEMP1_DIGIT1 == 3 #define PP_COUNTER_TEMP2_DIGIT1 3 #elif PP_COUNTER_TEMP1_DIGIT1 == 4 #define PP_COUNTER_TEMP2_DIGIT1 4 #elif PP_COUNTER_TEMP1_DIGIT1 == 5 #define PP_COUNTER_TEMP2_DIGIT1 5 #elif PP_COUNTER_TEMP1_DIGIT1 == 6 #define PP_COUNTER_TEMP2_DIGIT1 6 #elif PP_COUNTER_TEMP1_DIGIT1 == 7 #define PP_COUNTER_TEMP2_DIGIT1 7 #elif PP_COUNTER_TEMP1_DIGIT1 == 8 #define PP_COUNTER_TEMP2_DIGIT1 8 #elif PP_COUNTER_TEMP1_DIGIT1 == 9 #define PP_COUNTER_TEMP2_DIGIT1 9 #endif // PP_COUNTER_TEMP1_DIGIT1 #undef PP_COUNTER_TEMP2_DIGIT2 #if PP_COUNTER_TEMP1_DIGIT2 == 0 #define PP_COUNTER_TEMP2_DIGIT2 0 #elif PP_COUNTER_TEMP1_DIGIT2 == 1 #define PP_COUNTER_TEMP2_DIGIT2 1 #elif PP_COUNTER_TEMP1_DIGIT2 == 2 #define PP_COUNTER_TEMP2_DIGIT2 2 #elif PP_COUNTER_TEMP1_DIGIT2 == 3 #define PP_COUNTER_TEMP2_DIGIT2 3 #elif PP_COUNTER_TEMP1_DIGIT2 == 4 #define PP_COUNTER_TEMP2_DIGIT2 4 #elif PP_COUNTER_TEMP1_DIGIT2 == 5 #define PP_COUNTER_TEMP2_DIGIT2 5 #elif PP_COUNTER_TEMP1_DIGIT2 == 6 #define PP_COUNTER_TEMP2_DIGIT2 6 #elif PP_COUNTER_TEMP1_DIGIT2 == 7 #define PP_COUNTER_TEMP2_DIGIT2 7 #elif PP_COUNTER_TEMP1_DIGIT2 == 8 #define PP_COUNTER_TEMP2_DIGIT2 8 #elif PP_COUNTER_TEMP1_DIGIT2 == 9 #define PP_COUNTER_TEMP2_DIGIT2 9 #endif // PP_COUNTER_TEMP1_DIGIT2 #undef PP_COUNTER_TEMP2_DIGIT3 #if PP_COUNTER_TEMP1_DIGIT3 == 0 #define PP_COUNTER_TEMP2_DIGIT3 0 #elif PP_COUNTER_TEMP1_DIGIT3 == 1 #define PP_COUNTER_TEMP2_DIGIT3 1 #elif PP_COUNTER_TEMP1_DIGIT3 == 2 #define PP_COUNTER_TEMP2_DIGIT3 2 #elif PP_COUNTER_TEMP1_DIGIT3 == 3 #define PP_COUNTER_TEMP2_DIGIT3 3 #elif PP_COUNTER_TEMP1_DIGIT3 == 4 #define PP_COUNTER_TEMP2_DIGIT3 4 #elif PP_COUNTER_TEMP1_DIGIT3 == 5 #define PP_COUNTER_TEMP2_DIGIT3 5 #elif PP_COUNTER_TEMP1_DIGIT3 == 6 #define PP_COUNTER_TEMP2_DIGIT3 6 #elif PP_COUNTER_TEMP1_DIGIT3 == 7 #define PP_COUNTER_TEMP2_DIGIT3 7 #elif PP_COUNTER_TEMP1_DIGIT3 == 8 #define PP_COUNTER_TEMP2_DIGIT3 8 #elif PP_COUNTER_TEMP1_DIGIT3 == 9 #define PP_COUNTER_TEMP2_DIGIT3 9 #endif // PP_COUNTER_TEMP1_DIGIT3 #undef PP_COUNTER_TEMP2_DIGIT4 #if PP_COUNTER_TEMP1_DIGIT4 == 0 #define PP_COUNTER_TEMP2_DIGIT4 0 #elif PP_COUNTER_TEMP1_DIGIT4 == 1 #define PP_COUNTER_TEMP2_DIGIT4 1 #elif PP_COUNTER_TEMP1_DIGIT4 == 2 #define PP_COUNTER_TEMP2_DIGIT4 2 #elif PP_COUNTER_TEMP1_DIGIT4 == 3 #define PP_COUNTER_TEMP2_DIGIT4 3 #elif PP_COUNTER_TEMP1_DIGIT4 == 4 #define PP_COUNTER_TEMP2_DIGIT4 4 #elif PP_COUNTER_TEMP1_DIGIT4 == 5 #define PP_COUNTER_TEMP2_DIGIT4 5 #elif PP_COUNTER_TEMP1_DIGIT4 == 6 #define PP_COUNTER_TEMP2_DIGIT4 6 #elif PP_COUNTER_TEMP1_DIGIT4 == 7 #define PP_COUNTER_TEMP2_DIGIT4 7 #elif PP_COUNTER_TEMP1_DIGIT4 == 8 #define PP_COUNTER_TEMP2_DIGIT4 8 #elif PP_COUNTER_TEMP1_DIGIT4 == 9 #define PP_COUNTER_TEMP2_DIGIT4 9 #endif // PP_COUNTER_TEMP1_DIGIT4 #undef PP_COUNTER_TEMP2_DIGIT5 #if PP_COUNTER_TEMP1_DIGIT5 == 0 #define PP_COUNTER_TEMP2_DIGIT5 0 #elif PP_COUNTER_TEMP1_DIGIT5 == 1 #define PP_COUNTER_TEMP2_DIGIT5 1 #elif PP_COUNTER_TEMP1_DIGIT5 == 2 #define PP_COUNTER_TEMP2_DIGIT5 2 #elif PP_COUNTER_TEMP1_DIGIT5 == 3 #define PP_COUNTER_TEMP2_DIGIT5 3 #elif PP_COUNTER_TEMP1_DIGIT5 == 4 #define PP_COUNTER_TEMP2_DIGIT5 4 #elif PP_COUNTER_TEMP1_DIGIT5 == 5 #define PP_COUNTER_TEMP2_DIGIT5 5 #elif PP_COUNTER_TEMP1_DIGIT5 == 6 #define PP_COUNTER_TEMP2_DIGIT5 6 #elif PP_COUNTER_TEMP1_DIGIT5 == 7 #define PP_COUNTER_TEMP2_DIGIT5 7 #elif PP_COUNTER_TEMP1_DIGIT5 == 8 #define PP_COUNTER_TEMP2_DIGIT5 8 #elif PP_COUNTER_TEMP1_DIGIT5 == 9 #define PP_COUNTER_TEMP2_DIGIT5 9 #endif // PP_COUNTER_TEMP1_DIGIT5 #undef PP_COUNTER_TEMP1 #undef PP_COUNTER_TEMP1_DIGIT0 #undef PP_COUNTER_TEMP1_DIGIT1 #undef PP_COUNTER_TEMP1_DIGIT2 #undef PP_COUNTER_TEMP1_DIGIT3 #undef PP_COUNTER_TEMP1_DIGIT4 #undef PP_COUNTER_TEMP1_DIGIT5 #undef PP_COUNTER_TEMP3_DIGIT0 #if PP_COUNTER_TEMP2_DIGIT0 == 0 #define PP_COUNTER_TEMP3_DIGIT0 0 #elif PP_COUNTER_TEMP2_DIGIT0 == 1 #define PP_COUNTER_TEMP3_DIGIT0 1 #elif PP_COUNTER_TEMP2_DIGIT0 == 2 #define PP_COUNTER_TEMP3_DIGIT0 2 #elif PP_COUNTER_TEMP2_DIGIT0 == 3 #define PP_COUNTER_TEMP3_DIGIT0 3 #elif PP_COUNTER_TEMP2_DIGIT0 == 4 #define PP_COUNTER_TEMP3_DIGIT0 4 #elif PP_COUNTER_TEMP2_DIGIT0 == 5 #define PP_COUNTER_TEMP3_DIGIT0 5 #elif PP_COUNTER_TEMP2_DIGIT0 == 6 #define PP_COUNTER_TEMP3_DIGIT0 6 #elif PP_COUNTER_TEMP2_DIGIT0 == 7 #define PP_COUNTER_TEMP3_DIGIT0 7 #elif PP_COUNTER_TEMP2_DIGIT0 == 8 #define PP_COUNTER_TEMP3_DIGIT0 8 #elif PP_COUNTER_TEMP2_DIGIT0 == 9 #define PP_COUNTER_TEMP3_DIGIT0 9 #endif // PP_COUNTER_TEMP2_DIGIT0 #undef PP_COUNTER_TEMP3_DIGIT1 #if PP_COUNTER_TEMP2_DIGIT1 == 0 #define PP_COUNTER_TEMP3_DIGIT1 0 #elif PP_COUNTER_TEMP2_DIGIT1 == 1 #define PP_COUNTER_TEMP3_DIGIT1 1 #elif PP_COUNTER_TEMP2_DIGIT1 == 2 #define PP_COUNTER_TEMP3_DIGIT1 2 #elif PP_COUNTER_TEMP2_DIGIT1 == 3 #define PP_COUNTER_TEMP3_DIGIT1 3 #elif PP_COUNTER_TEMP2_DIGIT1 == 4 #define PP_COUNTER_TEMP3_DIGIT1 4 #elif PP_COUNTER_TEMP2_DIGIT1 == 5 #define PP_COUNTER_TEMP3_DIGIT1 5 #elif PP_COUNTER_TEMP2_DIGIT1 == 6 #define PP_COUNTER_TEMP3_DIGIT1 6 #elif PP_COUNTER_TEMP2_DIGIT1 == 7 #define PP_COUNTER_TEMP3_DIGIT1 7 #elif PP_COUNTER_TEMP2_DIGIT1 == 8 #define PP_COUNTER_TEMP3_DIGIT1 8 #elif PP_COUNTER_TEMP2_DIGIT1 == 9 #define PP_COUNTER_TEMP3_DIGIT1 9 #endif // PP_COUNTER_TEMP2_DIGIT1 #undef PP_COUNTER_TEMP3_DIGIT2 #if PP_COUNTER_TEMP2_DIGIT2 == 0 #define PP_COUNTER_TEMP3_DIGIT2 0 #elif PP_COUNTER_TEMP2_DIGIT2 == 1 #define PP_COUNTER_TEMP3_DIGIT2 1 #elif PP_COUNTER_TEMP2_DIGIT2 == 2 #define PP_COUNTER_TEMP3_DIGIT2 2 #elif PP_COUNTER_TEMP2_DIGIT2 == 3 #define PP_COUNTER_TEMP3_DIGIT2 3 #elif PP_COUNTER_TEMP2_DIGIT2 == 4 #define PP_COUNTER_TEMP3_DIGIT2 4 #elif PP_COUNTER_TEMP2_DIGIT2 == 5 #define PP_COUNTER_TEMP3_DIGIT2 5 #elif PP_COUNTER_TEMP2_DIGIT2 == 6 #define PP_COUNTER_TEMP3_DIGIT2 6 #elif PP_COUNTER_TEMP2_DIGIT2 == 7 #define PP_COUNTER_TEMP3_DIGIT2 7 #elif PP_COUNTER_TEMP2_DIGIT2 == 8 #define PP_COUNTER_TEMP3_DIGIT2 8 #elif PP_COUNTER_TEMP2_DIGIT2 == 9 #define PP_COUNTER_TEMP3_DIGIT2 9 #endif // PP_COUNTER_TEMP2_DIGIT2 #undef PP_COUNTER_TEMP3_DIGIT3 #if PP_COUNTER_TEMP2_DIGIT3 == 0 #define PP_COUNTER_TEMP3_DIGIT3 0 #elif PP_COUNTER_TEMP2_DIGIT3 == 1 #define PP_COUNTER_TEMP3_DIGIT3 1 #elif PP_COUNTER_TEMP2_DIGIT3 == 2 #define PP_COUNTER_TEMP3_DIGIT3 2 #elif PP_COUNTER_TEMP2_DIGIT3 == 3 #define PP_COUNTER_TEMP3_DIGIT3 3 #elif PP_COUNTER_TEMP2_DIGIT3 == 4 #define PP_COUNTER_TEMP3_DIGIT3 4 #elif PP_COUNTER_TEMP2_DIGIT3 == 5 #define PP_COUNTER_TEMP3_DIGIT3 5 #elif PP_COUNTER_TEMP2_DIGIT3 == 6 #define PP_COUNTER_TEMP3_DIGIT3 6 #elif PP_COUNTER_TEMP2_DIGIT3 == 7 #define PP_COUNTER_TEMP3_DIGIT3 7 #elif PP_COUNTER_TEMP2_DIGIT3 == 8 #define PP_COUNTER_TEMP3_DIGIT3 8 #elif PP_COUNTER_TEMP2_DIGIT3 == 9 #define PP_COUNTER_TEMP3_DIGIT3 9 #endif // PP_COUNTER_TEMP2_DIGIT3 #undef PP_COUNTER_TEMP3_DIGIT4 #if PP_COUNTER_TEMP2_DIGIT4 == 0 #define PP_COUNTER_TEMP3_DIGIT4 0 #elif PP_COUNTER_TEMP2_DIGIT4 == 1 #define PP_COUNTER_TEMP3_DIGIT4 1 #elif PP_COUNTER_TEMP2_DIGIT4 == 2 #define PP_COUNTER_TEMP3_DIGIT4 2 #elif PP_COUNTER_TEMP2_DIGIT4 == 3 #define PP_COUNTER_TEMP3_DIGIT4 3 #elif PP_COUNTER_TEMP2_DIGIT4 == 4 #define PP_COUNTER_TEMP3_DIGIT4 4 #elif PP_COUNTER_TEMP2_DIGIT4 == 5 #define PP_COUNTER_TEMP3_DIGIT4 5 #elif PP_COUNTER_TEMP2_DIGIT4 == 6 #define PP_COUNTER_TEMP3_DIGIT4 6 #elif PP_COUNTER_TEMP2_DIGIT4 == 7 #define PP_COUNTER_TEMP3_DIGIT4 7 #elif PP_COUNTER_TEMP2_DIGIT4 == 8 #define PP_COUNTER_TEMP3_DIGIT4 8 #elif PP_COUNTER_TEMP2_DIGIT4 == 9 #define PP_COUNTER_TEMP3_DIGIT4 9 #endif // PP_COUNTER_TEMP2_DIGIT4 #undef PP_COUNTER_TEMP3_DIGIT5 #if PP_COUNTER_TEMP2_DIGIT5 == 0 #define PP_COUNTER_TEMP3_DIGIT5 0 #elif PP_COUNTER_TEMP2_DIGIT5 == 1 #define PP_COUNTER_TEMP3_DIGIT5 1 #elif PP_COUNTER_TEMP2_DIGIT5 == 2 #define PP_COUNTER_TEMP3_DIGIT5 2 #elif PP_COUNTER_TEMP2_DIGIT5 == 3 #define PP_COUNTER_TEMP3_DIGIT5 3 #elif PP_COUNTER_TEMP2_DIGIT5 == 4 #define PP_COUNTER_TEMP3_DIGIT5 4 #elif PP_COUNTER_TEMP2_DIGIT5 == 5 #define PP_COUNTER_TEMP3_DIGIT5 5 #elif PP_COUNTER_TEMP2_DIGIT5 == 6 #define PP_COUNTER_TEMP3_DIGIT5 6 #elif PP_COUNTER_TEMP2_DIGIT5 == 7 #define PP_COUNTER_TEMP3_DIGIT5 7 #elif PP_COUNTER_TEMP2_DIGIT5 == 8 #define PP_COUNTER_TEMP3_DIGIT5 8 #elif PP_COUNTER_TEMP2_DIGIT5 == 9 #define PP_COUNTER_TEMP3_DIGIT5 9 #endif // PP_COUNTER_TEMP2_DIGIT5 #undef PP_COUNTER_TEMP2_DIGIT0 #undef PP_COUNTER_TEMP2_DIGIT1 #undef PP_COUNTER_TEMP2_DIGIT2 #undef PP_COUNTER_TEMP2_DIGIT3 #undef PP_COUNTER_TEMP2_DIGIT4 #undef PP_COUNTER_TEMP2_DIGIT5 #undef PP_COUNTER_TEMP3 #define PP_COUNTER_TEMP3 PP_MAKE_INT(PP_COUNTER_TEMP3_DIGIT5,PP_COUNTER_TEMP3_DIGIT4,PP_COUNTER_TEMP3_DIGIT3,PP_COUNTER_TEMP3_DIGIT2,PP_COUNTER_TEMP3_DIGIT1,PP_COUNTER_TEMP3_DIGIT0) #undef PP_COUNTER #define PP_COUNTER PP_COUNTER_TEMP3
PP_COUNTER_TEMP1 は新しい値を持ちますが古い PP_COUNTER に関係付けられたものです。作業用に必要なだけのものなので必要なくなった時点で #undef しても構いません
PP_COUNTER_TEMP2 は新しい値を PP_COUNTER から関係を切り離すために必要なものです。作業用に必要なだけのものなので必要なくなった時点で #undef しても構いません
PP_COUNTER_TEMP3 は新しい PP_COUNTER となるべきものです。PC_COUNTER を使っている間必要なものなので #undef してはいけません
こうすると二度目以降も問題なく数値を更新できるようになります
式の計算結果を得る
次のようなマクロがあったときに、value_ に 1+1 のような式を指定することはできません
#define FOO( value_ ) struct PP_CONCAT(foo,value_) { static const int value = value_; } FOO( 1+1 ); // エラー
式をマクロにしてみても同じです
#define PP_VALUE (1+1) FOO( PP_VALUE ); // エラー
これはマクロの置換が単純な文字列の置換でしかないということが原因です
1+1 はあくまでも 1+1 です
マクロの置換で 1+1 が 2 になったりはしません
しかし 1+1 を 2 にしてもらいたいときもあるでしょう
なんとか実現することはできないでしょうか
実は既に実現しています
上記の pp_counter_inc.inl では PP_COUNTER_TEMP1 に PP_COUNTER+1 という式を指定していますが、新しい PP_COUNTER は単純な数値に置換されます
これは式の計算結果を得ているということです
置換では 1+1 は 1+1 のままなのですが、#if などの条件式では 1+1 は 2 と評価されます
これを利用して式の計算結果とまったく同じ値のマクロを別に定義することで機能を実現しています
この式の計算結果を得るという機能はカウンタの機能とは独立したものなので、次のように書き直してもいいかもしれません
pp_value.inl
#if defined( PP_VALUE ) #define PP_VALUE_TEMP1 PP_VALUE #define PP_VALUE_TEMP1_DIGIT0 PP_DIGIT0(PP_VALUE_TEMP1) #define PP_VALUE_TEMP1_DIGIT1 PP_DIGIT1(PP_VALUE_TEMP1) #define PP_VALUE_TEMP1_DIGIT2 PP_DIGIT2(PP_VALUE_TEMP1) #define PP_VALUE_TEMP1_DIGIT3 PP_DIGIT3(PP_VALUE_TEMP1) #define PP_VALUE_TEMP1_DIGIT4 PP_DIGIT4(PP_VALUE_TEMP1) #define PP_VALUE_TEMP1_DIGIT5 PP_DIGIT5(PP_VALUE_TEMP1) #undef PP_VALUE_TEMP2_DIGIT0 #if PP_VALUE_TEMP1_DIGIT0 == 0 #define PP_VALUE_TEMP2_DIGIT0 0 #elif PP_VALUE_TEMP1_DIGIT0 == 1 #define PP_VALUE_TEMP2_DIGIT0 1 #elif PP_VALUE_TEMP1_DIGIT0 == 2 #define PP_VALUE_TEMP2_DIGIT0 2 #elif PP_VALUE_TEMP1_DIGIT0 == 3 #define PP_VALUE_TEMP2_DIGIT0 3 #elif PP_VALUE_TEMP1_DIGIT0 == 4 #define PP_VALUE_TEMP2_DIGIT0 4 #elif PP_VALUE_TEMP1_DIGIT0 == 5 #define PP_VALUE_TEMP2_DIGIT0 5 #elif PP_VALUE_TEMP1_DIGIT0 == 6 #define PP_VALUE_TEMP2_DIGIT0 6 #elif PP_VALUE_TEMP1_DIGIT0 == 7 #define PP_VALUE_TEMP2_DIGIT0 7 #elif PP_VALUE_TEMP1_DIGIT0 == 8 #define PP_VALUE_TEMP2_DIGIT0 8 #elif PP_VALUE_TEMP1_DIGIT0 == 9 #define PP_VALUE_TEMP2_DIGIT0 9 #endif // PP_VALUE_TEMP1_DIGIT0 #undef PP_VALUE_TEMP2_DIGIT1 #if PP_VALUE_TEMP1_DIGIT1 == 0 #define PP_VALUE_TEMP2_DIGIT1 0 #elif PP_VALUE_TEMP1_DIGIT1 == 1 #define PP_VALUE_TEMP2_DIGIT1 1 #elif PP_VALUE_TEMP1_DIGIT1 == 2 #define PP_VALUE_TEMP2_DIGIT1 2 #elif PP_VALUE_TEMP1_DIGIT1 == 3 #define PP_VALUE_TEMP2_DIGIT1 3 #elif PP_VALUE_TEMP1_DIGIT1 == 4 #define PP_VALUE_TEMP2_DIGIT1 4 #elif PP_VALUE_TEMP1_DIGIT1 == 5 #define PP_VALUE_TEMP2_DIGIT1 5 #elif PP_VALUE_TEMP1_DIGIT1 == 6 #define PP_VALUE_TEMP2_DIGIT1 6 #elif PP_VALUE_TEMP1_DIGIT1 == 7 #define PP_VALUE_TEMP2_DIGIT1 7 #elif PP_VALUE_TEMP1_DIGIT1 == 8 #define PP_VALUE_TEMP2_DIGIT1 8 #elif PP_VALUE_TEMP1_DIGIT1 == 9 #define PP_VALUE_TEMP2_DIGIT1 9 #endif // PP_VALUE_TEMP1_DIGIT1 #undef PP_VALUE_TEMP2_DIGIT2 #if PP_VALUE_TEMP1_DIGIT2 == 0 #define PP_VALUE_TEMP2_DIGIT2 0 #elif PP_VALUE_TEMP1_DIGIT2 == 1 #define PP_VALUE_TEMP2_DIGIT2 1 #elif PP_VALUE_TEMP1_DIGIT2 == 2 #define PP_VALUE_TEMP2_DIGIT2 2 #elif PP_VALUE_TEMP1_DIGIT2 == 3 #define PP_VALUE_TEMP2_DIGIT2 3 #elif PP_VALUE_TEMP1_DIGIT2 == 4 #define PP_VALUE_TEMP2_DIGIT2 4 #elif PP_VALUE_TEMP1_DIGIT2 == 5 #define PP_VALUE_TEMP2_DIGIT2 5 #elif PP_VALUE_TEMP1_DIGIT2 == 6 #define PP_VALUE_TEMP2_DIGIT2 6 #elif PP_VALUE_TEMP1_DIGIT2 == 7 #define PP_VALUE_TEMP2_DIGIT2 7 #elif PP_VALUE_TEMP1_DIGIT2 == 8 #define PP_VALUE_TEMP2_DIGIT2 8 #elif PP_VALUE_TEMP1_DIGIT2 == 9 #define PP_VALUE_TEMP2_DIGIT2 9 #endif // PP_VALUE_TEMP1_DIGIT2 #undef PP_VALUE_TEMP2_DIGIT3 #if PP_VALUE_TEMP1_DIGIT3 == 0 #define PP_VALUE_TEMP2_DIGIT3 0 #elif PP_VALUE_TEMP1_DIGIT3 == 1 #define PP_VALUE_TEMP2_DIGIT3 1 #elif PP_VALUE_TEMP1_DIGIT3 == 2 #define PP_VALUE_TEMP2_DIGIT3 2 #elif PP_VALUE_TEMP1_DIGIT3 == 3 #define PP_VALUE_TEMP2_DIGIT3 3 #elif PP_VALUE_TEMP1_DIGIT3 == 4 #define PP_VALUE_TEMP2_DIGIT3 4 #elif PP_VALUE_TEMP1_DIGIT3 == 5 #define PP_VALUE_TEMP2_DIGIT3 5 #elif PP_VALUE_TEMP1_DIGIT3 == 6 #define PP_VALUE_TEMP2_DIGIT3 6 #elif PP_VALUE_TEMP1_DIGIT3 == 7 #define PP_VALUE_TEMP2_DIGIT3 7 #elif PP_VALUE_TEMP1_DIGIT3 == 8 #define PP_VALUE_TEMP2_DIGIT3 8 #elif PP_VALUE_TEMP1_DIGIT3 == 9 #define PP_VALUE_TEMP2_DIGIT3 9 #endif // PP_VALUE_TEMP1_DIGIT3 #undef PP_VALUE_TEMP2_DIGIT4 #if PP_VALUE_TEMP1_DIGIT4 == 0 #define PP_VALUE_TEMP2_DIGIT4 0 #elif PP_VALUE_TEMP1_DIGIT4 == 1 #define PP_VALUE_TEMP2_DIGIT4 1 #elif PP_VALUE_TEMP1_DIGIT4 == 2 #define PP_VALUE_TEMP2_DIGIT4 2 #elif PP_VALUE_TEMP1_DIGIT4 == 3 #define PP_VALUE_TEMP2_DIGIT4 3 #elif PP_VALUE_TEMP1_DIGIT4 == 4 #define PP_VALUE_TEMP2_DIGIT4 4 #elif PP_VALUE_TEMP1_DIGIT4 == 5 #define PP_VALUE_TEMP2_DIGIT4 5 #elif PP_VALUE_TEMP1_DIGIT4 == 6 #define PP_VALUE_TEMP2_DIGIT4 6 #elif PP_VALUE_TEMP1_DIGIT4 == 7 #define PP_VALUE_TEMP2_DIGIT4 7 #elif PP_VALUE_TEMP1_DIGIT4 == 8 #define PP_VALUE_TEMP2_DIGIT4 8 #elif PP_VALUE_TEMP1_DIGIT4 == 9 #define PP_VALUE_TEMP2_DIGIT4 9 #endif // PP_VALUE_TEMP1_DIGIT4 #undef PP_VALUE_TEMP2_DIGIT5 #if PP_VALUE_TEMP1_DIGIT5 == 0 #define PP_VALUE_TEMP2_DIGIT5 0 #elif PP_VALUE_TEMP1_DIGIT5 == 1 #define PP_VALUE_TEMP2_DIGIT5 1 #elif PP_VALUE_TEMP1_DIGIT5 == 2 #define PP_VALUE_TEMP2_DIGIT5 2 #elif PP_VALUE_TEMP1_DIGIT5 == 3 #define PP_VALUE_TEMP2_DIGIT5 3 #elif PP_VALUE_TEMP1_DIGIT5 == 4 #define PP_VALUE_TEMP2_DIGIT5 4 #elif PP_VALUE_TEMP1_DIGIT5 == 5 #define PP_VALUE_TEMP2_DIGIT5 5 #elif PP_VALUE_TEMP1_DIGIT5 == 6 #define PP_VALUE_TEMP2_DIGIT5 6 #elif PP_VALUE_TEMP1_DIGIT5 == 7 #define PP_VALUE_TEMP2_DIGIT5 7 #elif PP_VALUE_TEMP1_DIGIT5 == 8 #define PP_VALUE_TEMP2_DIGIT5 8 #elif PP_VALUE_TEMP1_DIGIT5 == 9 #define PP_VALUE_TEMP2_DIGIT5 9 #endif // PP_VALUE_TEMP1_DIGIT5 #undef PP_VALUE_TEMP1 #undef PP_VALUE_TEMP1_DIGIT0 #undef PP_VALUE_TEMP1_DIGIT1 #undef PP_VALUE_TEMP1_DIGIT2 #undef PP_VALUE_TEMP1_DIGIT3 #undef PP_VALUE_TEMP1_DIGIT4 #undef PP_VALUE_TEMP1_DIGIT5 #undef PP_VALUE_TEMP3_DIGIT0 #if PP_VALUE_TEMP2_DIGIT0 == 0 #define PP_VALUE_TEMP3_DIGIT0 0 #elif PP_VALUE_TEMP2_DIGIT0 == 1 #define PP_VALUE_TEMP3_DIGIT0 1 #elif PP_VALUE_TEMP2_DIGIT0 == 2 #define PP_VALUE_TEMP3_DIGIT0 2 #elif PP_VALUE_TEMP2_DIGIT0 == 3 #define PP_VALUE_TEMP3_DIGIT0 3 #elif PP_VALUE_TEMP2_DIGIT0 == 4 #define PP_VALUE_TEMP3_DIGIT0 4 #elif PP_VALUE_TEMP2_DIGIT0 == 5 #define PP_VALUE_TEMP3_DIGIT0 5 #elif PP_VALUE_TEMP2_DIGIT0 == 6 #define PP_VALUE_TEMP3_DIGIT0 6 #elif PP_VALUE_TEMP2_DIGIT0 == 7 #define PP_VALUE_TEMP3_DIGIT0 7 #elif PP_VALUE_TEMP2_DIGIT0 == 8 #define PP_VALUE_TEMP3_DIGIT0 8 #elif PP_VALUE_TEMP2_DIGIT0 == 9 #define PP_VALUE_TEMP3_DIGIT0 9 #endif // PP_VALUE_TEMP2_DIGIT0 #undef PP_VALUE_TEMP3_DIGIT1 #if PP_VALUE_TEMP2_DIGIT1 == 0 #define PP_VALUE_TEMP3_DIGIT1 0 #elif PP_VALUE_TEMP2_DIGIT1 == 1 #define PP_VALUE_TEMP3_DIGIT1 1 #elif PP_VALUE_TEMP2_DIGIT1 == 2 #define PP_VALUE_TEMP3_DIGIT1 2 #elif PP_VALUE_TEMP2_DIGIT1 == 3 #define PP_VALUE_TEMP3_DIGIT1 3 #elif PP_VALUE_TEMP2_DIGIT1 == 4 #define PP_VALUE_TEMP3_DIGIT1 4 #elif PP_VALUE_TEMP2_DIGIT1 == 5 #define PP_VALUE_TEMP3_DIGIT1 5 #elif PP_VALUE_TEMP2_DIGIT1 == 6 #define PP_VALUE_TEMP3_DIGIT1 6 #elif PP_VALUE_TEMP2_DIGIT1 == 7 #define PP_VALUE_TEMP3_DIGIT1 7 #elif PP_VALUE_TEMP2_DIGIT1 == 8 #define PP_VALUE_TEMP3_DIGIT1 8 #elif PP_VALUE_TEMP2_DIGIT1 == 9 #define PP_VALUE_TEMP3_DIGIT1 9 #endif // PP_VALUE_TEMP2_DIGIT1 #undef PP_VALUE_TEMP3_DIGIT2 #if PP_VALUE_TEMP2_DIGIT2 == 0 #define PP_VALUE_TEMP3_DIGIT2 0 #elif PP_VALUE_TEMP2_DIGIT2 == 1 #define PP_VALUE_TEMP3_DIGIT2 1 #elif PP_VALUE_TEMP2_DIGIT2 == 2 #define PP_VALUE_TEMP3_DIGIT2 2 #elif PP_VALUE_TEMP2_DIGIT2 == 3 #define PP_VALUE_TEMP3_DIGIT2 3 #elif PP_VALUE_TEMP2_DIGIT2 == 4 #define PP_VALUE_TEMP3_DIGIT2 4 #elif PP_VALUE_TEMP2_DIGIT2 == 5 #define PP_VALUE_TEMP3_DIGIT2 5 #elif PP_VALUE_TEMP2_DIGIT2 == 6 #define PP_VALUE_TEMP3_DIGIT2 6 #elif PP_VALUE_TEMP2_DIGIT2 == 7 #define PP_VALUE_TEMP3_DIGIT2 7 #elif PP_VALUE_TEMP2_DIGIT2 == 8 #define PP_VALUE_TEMP3_DIGIT2 8 #elif PP_VALUE_TEMP2_DIGIT2 == 9 #define PP_VALUE_TEMP3_DIGIT2 9 #endif // PP_VALUE_TEMP2_DIGIT2 #undef PP_VALUE_TEMP3_DIGIT3 #if PP_VALUE_TEMP2_DIGIT3 == 0 #define PP_VALUE_TEMP3_DIGIT3 0 #elif PP_VALUE_TEMP2_DIGIT3 == 1 #define PP_VALUE_TEMP3_DIGIT3 1 #elif PP_VALUE_TEMP2_DIGIT3 == 2 #define PP_VALUE_TEMP3_DIGIT3 2 #elif PP_VALUE_TEMP2_DIGIT3 == 3 #define PP_VALUE_TEMP3_DIGIT3 3 #elif PP_VALUE_TEMP2_DIGIT3 == 4 #define PP_VALUE_TEMP3_DIGIT3 4 #elif PP_VALUE_TEMP2_DIGIT3 == 5 #define PP_VALUE_TEMP3_DIGIT3 5 #elif PP_VALUE_TEMP2_DIGIT3 == 6 #define PP_VALUE_TEMP3_DIGIT3 6 #elif PP_VALUE_TEMP2_DIGIT3 == 7 #define PP_VALUE_TEMP3_DIGIT3 7 #elif PP_VALUE_TEMP2_DIGIT3 == 8 #define PP_VALUE_TEMP3_DIGIT3 8 #elif PP_VALUE_TEMP2_DIGIT3 == 9 #define PP_VALUE_TEMP3_DIGIT3 9 #endif // PP_VALUE_TEMP2_DIGIT3 #undef PP_VALUE_TEMP3_DIGIT4 #if PP_VALUE_TEMP2_DIGIT4 == 0 #define PP_VALUE_TEMP3_DIGIT4 0 #elif PP_VALUE_TEMP2_DIGIT4 == 1 #define PP_VALUE_TEMP3_DIGIT4 1 #elif PP_VALUE_TEMP2_DIGIT4 == 2 #define PP_VALUE_TEMP3_DIGIT4 2 #elif PP_VALUE_TEMP2_DIGIT4 == 3 #define PP_VALUE_TEMP3_DIGIT4 3 #elif PP_VALUE_TEMP2_DIGIT4 == 4 #define PP_VALUE_TEMP3_DIGIT4 4 #elif PP_VALUE_TEMP2_DIGIT4 == 5 #define PP_VALUE_TEMP3_DIGIT4 5 #elif PP_VALUE_TEMP2_DIGIT4 == 6 #define PP_VALUE_TEMP3_DIGIT4 6 #elif PP_VALUE_TEMP2_DIGIT4 == 7 #define PP_VALUE_TEMP3_DIGIT4 7 #elif PP_VALUE_TEMP2_DIGIT4 == 8 #define PP_VALUE_TEMP3_DIGIT4 8 #elif PP_VALUE_TEMP2_DIGIT4 == 9 #define PP_VALUE_TEMP3_DIGIT4 9 #endif // PP_VALUE_TEMP2_DIGIT4 #undef PP_VALUE_TEMP3_DIGIT5 #if PP_VALUE_TEMP2_DIGIT5 == 0 #define PP_VALUE_TEMP3_DIGIT5 0 #elif PP_VALUE_TEMP2_DIGIT5 == 1 #define PP_VALUE_TEMP3_DIGIT5 1 #elif PP_VALUE_TEMP2_DIGIT5 == 2 #define PP_VALUE_TEMP3_DIGIT5 2 #elif PP_VALUE_TEMP2_DIGIT5 == 3 #define PP_VALUE_TEMP3_DIGIT5 3 #elif PP_VALUE_TEMP2_DIGIT5 == 4 #define PP_VALUE_TEMP3_DIGIT5 4 #elif PP_VALUE_TEMP2_DIGIT5 == 5 #define PP_VALUE_TEMP3_DIGIT5 5 #elif PP_VALUE_TEMP2_DIGIT5 == 6 #define PP_VALUE_TEMP3_DIGIT5 6 #elif PP_VALUE_TEMP2_DIGIT5 == 7 #define PP_VALUE_TEMP3_DIGIT5 7 #elif PP_VALUE_TEMP2_DIGIT5 == 8 #define PP_VALUE_TEMP3_DIGIT5 8 #elif PP_VALUE_TEMP2_DIGIT5 == 9 #define PP_VALUE_TEMP3_DIGIT5 9 #endif // PP_VALUE_TEMP2_DIGIT5 #undef PP_VALUE_TEMP2_DIGIT0 #undef PP_VALUE_TEMP2_DIGIT1 #undef PP_VALUE_TEMP2_DIGIT2 #undef PP_VALUE_TEMP2_DIGIT3 #undef PP_VALUE_TEMP2_DIGIT4 #undef PP_VALUE_TEMP2_DIGIT5 #undef PP_VALUE_TEMP3 #define PP_VALUE_TEMP3 PP_MAKE_INT(PP_VALUE_TEMP3_DIGIT5,PP_VALUE_TEMP3_DIGIT4,PP_VALUE_TEMP3_DIGIT3,PP_VALUE_TEMP3_DIGIT2,PP_VALUE_TEMP3_DIGIT1,PP_VALUE_TEMP3_DIGIT0) #undef PP_VALUE_NEW #define PP_VALUE_NEW PP_VALUE_TEMP3 #undef PP_VALUE #define PP_VALUE PP_VALUE_TEMP3 #endif // PP_VALUE
pp_counter_inc.inl
#undef PP_VALUE #define PP_VALUE (PP_COUNTER+1) #include "pp_value.inl" #undef PP_COUNTER #define PP_COUNTER PP_VALUE_NEW
ここで PP_COUNTER の新しい定義が PP_VALUE ではなく PP_VALUE_NEW となっていることに気を付けてください
これを PP_VALUE にしてしまうと二度目に pp_counter_inc.inl を #include したときに問題が起きます
#include "pp_counter_inc.inl" #include "pp_counter_inc.inl"
↓
//#include "pp_counter_inc.inl" . . . #define PP_COUNTER PP_VALUE //#include "pp_counter_inc.inl" #undef PP_VALUE #define PP_VALUE (PP_COUNTER+1) . . .
↓
#define PP_COUNTER PP_VALUE #undef PP_VALUE #define PP_VALUE (PP_VALUE+1) // PP_VALUE は #undef 済みなのでエラー
ここまでの機能を使った例を何か考えてみましょう
使用例その1
#define PP_POW10_0 1 #define PP_POW10_1 10 #define PP_POW10_2 100 #define PP_POW10_3 1000 #define PP_POW10_4 10000 #define PP_POW10_5 100000 #define PP_POW10_6 1000000 #define PP_POW10_7 10000000 #define PP_POW10_8 100000000 #define PP_POW10_9 1000000000 #define PP_POW10( n ) PP_CONCAT(PP_POW10_,n) #define PP_DIGIT0( value ) (((value)/PP_POW10(0))%10) #define PP_DIGIT1( value ) (((value)/PP_POW10(1))%10) #define PP_DIGIT2( value ) (((value)/PP_POW10(2))%10) #define PP_DIGIT3( value ) (((value)/PP_POW10(3))%10) #define PP_DIGIT4( value ) (((value)/PP_POW10(4))%10) #define PP_DIGIT5( value ) (((value)/PP_POW10(5))%10)
使用例その2
ここでは cfoo クラスの基底クラスを foo.inl に列挙しています
これを cfoo の宣言や初期化リストの記述に展開しています
基底クラスの並びも初期化リストの並びも最初は : で区切り、それ以降は , で区切るということを実現するためにマクロを使っています
foo.inl
DEFINE_FOO( foo ) #include "pp_counter_inc.inl" DEFINE_FOO( bar ) #include "pp_counter_inc.inl" DEFINE_FOO( baz ) #include "pp_counter_inc.inl" DEFINE_FOO( qux ) #include "pp_counter_inc.inl"
test.cpp
#define PP_COLON() : #define PP_COMMA() , #define PP_SEPARATOR( counter ) PP_IF(counter,PP_COMMA,PP_COLON)() #define PP_COUNTER 0 #define DEFINE_FOO( name ) struct csample_##name { csample_##name(){ debug_printf( #name "\n" ); } ~csample_##name(){ debug_printf( "~" #name "\n" ); }}; #include "foo.inl" #undef DEFINE_FOO #undef PP_COUNTER class cfoo #define PP_COUNTER 0 #define DEFINE_FOO( name ) PP_SEPARATOR(PP_COUNTER) public csample_##name #include "foo.inl" #undef DEFINE_FOO #undef PP_COUNTER { public: cfoo() #define PP_COUNTER 0 #define DEFINE_FOO( name ) PP_SEPARATOR(PP_COUNTER) csample_##name() #include "foo.inl" #undef DEFINE_FOO #undef PP_COUNTER { } }; int main(){ cfoo foo; return 0; }
実際にはこんなことをしなくてもダミーの基底クラスを最初か最後に追加すればいいだけですが、そうしてしまうとここまで書いてきた機能が必要なくなってしまうので例になりません
foo.inl
DEFINE_FOO( foo ) DEFINE_FOO( bar ) DEFINE_FOO( baz ) DEFINE_FOO( qux )
test.cpp
struct cfoo_empty {}; #define DEFINE_FOO( name ) struct csample_##name { csample_##name(){ debug_printf( #name "\n" ); } ~csample_##name(){ debug_printf( "~" #name "\n" ); }}; #include "foo.inl" #undef DEFINE_FOO class cfoo : public cfoo_empty #define DEFINE_FOO( name ) , public csample_##name #include "foo.inl" #undef DEFINE_FOO { public: cfoo(): cfoo_empty() #define DEFINE_FOO( name ) , csample_##name() #include "foo.inl" #undef DEFINE_FOO { } }; int main(){ cfoo foo; return 0; }
仕事では、このように余計なことをせずとも単純な解決方法があるなら特に事情のない限り単純な方を採用すべきだということに気を付けてください
簡単にできることは簡単に済ませる方が無駄に難しいことをするよりずっとよいことです