!!! C言語のマクロのオーバーロード {{category ScrapCode,"C/C++",nolink}}同じ名前のマクロに対して、渡す引数の数に応じて異なる処理(マクロ)を呼び出す(展開する)。 C/C++ のマクロでは、可変長引数マクロ(__VA_ARGS__)とマクロの連結(##)を組み合わせることで、擬似的にオーバーロードを実現する。 なお、古いMSVCでは、コンパイラがマクロを正しく展開できない(__VA_ARGS__ を一つの引数として誤認識する)。 そのため、一つマクロ展開をはさむことで、VC++ のプリプロセッサがマクロを正確に再帰評価し、意図した通りのマクロのオーバーロードとして動作が可能となる。 !!マクロのオーバーロード(単純版) 引数の数に応じて展開するマクロを選択する。 SELECTER の定義および呼び出す際のマクロの列挙は、必要に応じて変更する。 // 呼び出されるマクロ #define MACRO_1(a) ptintf("1") #define MACRO_2(a, b) ptintf("2") #define MACRO_3(a, b, c) ptintf("3") #define MACRO_4(a, b, c, d) ptintf("4") #define MACRO_5(a, b, c, d, e) ptintf("5") // マクロのオーバーロード(単純版) #define EXPAND(x) x #define SELECTER(m1, m2, m3, m4, m5, NAME, ...) NAME #define MY_MACRO(...) EXPAND(SELECTER(__VA_ARGS__, MACRO_5, MACRO_4, MACRO_3, MACRO_2, MACRO_1)(__VA_ARGS__)) void main() { MY_MACRO(10); // MACRO_1 が呼ばれる MY_MACRO(10, 20); // MACRO_2 が呼ばれる } !!マクロのオーバーロード(一般化版) 呼び出すマクロが MACRO_1、MACRO_2 ... のように マクロ名+引数の数 と一般化して、引数の数で呼び出すマクロを選択する。 // 呼び出されるマクロ #define MACRO_1(a) ptintf("1") #define MACRO_2(a, b) ptintf("2") #define MACRO_3(a, b, c) ptintf("3") #define MACRO_4(a, b, c, d) ptintf("4") #define MACRO_5(a, b, c, d, e) ptintf("5") // マクロのオーバーロード #define EXPAND(x) x #define _VA_COUNT(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, COUNRTER, ... ) COUNRTER #define _VA_NUMBER(...) EXPAND(_VA_COUNT( __VA_ARGS__ , 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 )) #define _VA_CONCAT(a, b) a##b #define _VA_SELECTER(macro, count) _VA_CONCAT(macro, count) #define MY_MACRO(...) EXPAND(_VA_SELECTER(MACRO_,_VA_NUMBER(__VA_ARGS__))(__VA_ARGS__)) void main() { MY_MACRO(10); // MACRO_1 が呼ばれる MY_MACRO(10, 20); // MACRO_2 が呼ばれる }