トップ 履歴 一覧 カテゴリ ソース 検索 ヘルプ RSS ログイン

ScrapCode/C/MacroOverload

INDEX

C言語のマクロのオーバーロード

同じ名前のマクロに対して、渡す引数の数に応じて異なる処理(マクロ)を呼び出す(展開する)。

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 が呼ばれる
}

最終更新時間:2026年07月10日 09時16分59秒 指摘や意見などあればSandBoxのBBSへ。