はい、できます。以下は最大 4 つの引数をサポートしますが、それ以上の引数をサポートするように簡単に拡張できます。
#define MACRO(api, ...) \
bool ret = api(__VA_ARGS__ VA_COMMA(__VA_ARGS__) 456)
/*
* VA_COMMA() expands to nothing if given no arguments and a comma if
* given 1 to 4 arguments. Bad things happen if given more than 4
* arguments. Don't do it.
*/
#define VA_COMMA(...) GET_6TH_ARG(,##__VA_ARGS__,COMMA,COMMA,COMMA,COMMA,)
#define GET_6TH_ARG(a1,a2,a3,a4,a5,a6,...) a6
#define COMMA ,
/* EXAMPLES */
MACRO(foo) /* bool ret = foo( 456) */
MACRO(foo,1) /* bool ret = foo(1 , 456) */
MACRO(foo,1,2,3,4) /* bool ret = foo(1,2,3,4 , 456) */
/* uh oh, too many arguments: */
MACRO(foo,1,2,3,4,5) /* bool ret = foo(1,2,3,4,5 5 456) */
MACRO(foo,1,2,3,4,5,6) /* bool ret = foo(1,2,3,4,5,6 5 456) */
この同じトリックは、次の目的で使用されます。
説明
VA_COMMA
は、その引数 ( __VA_ARGS__
) を 6 つの追加の引数で囲みます。前に 1 つの空の引数 (空である必要はありません。破棄されます) と、4 つのコンマと後の空の引数です。
これらの 6 つ以上の引数は に渡されGET_6TH_ARG
、その名前が示すように、6 番目の引数に展開されます。他のすべての引数は破棄されます。
したがって、次のようにMACRO(foo)
展開されます。
step 0: MACRO(foo)
step 1: bool ret = foo( VA_COMMA() 456)
step 2: bool ret = foo( GET_6TH_ARG(,COMMA,COMMA,COMMA,COMMA,) 456)
step 3: bool ret = foo( 456)
MACRO(foo,1)
は次のように展開されます。
step 0: MACRO(foo,1)
step 1: bool ret = foo(1 VA_COMMA(1) 456)
step 2: bool ret = foo(1 GET_6TH_ARG(,1,COMMA,COMMA,COMMA,COMMA,) 456)
step 3: bool ret = foo(1 COMMA 456)
step 4: bool ret = foo(1 , 456)
MACRO(foo,1,2)
は次のように展開されます。
step 0: MACRO(foo,1,2)
step 1: bool ret = foo(1,2 VA_COMMA(1,2) 456)
step 2: bool ret = foo(1,2 GET_6TH_ARG(,1,2,COMMA,COMMA,COMMA,COMMA,) 456)
step 3: bool ret = foo(1,2 COMMA 456)
step 4: bool ret = foo(1,2 , 456)
MACRO(foo,1,2,3,4,5)
は次のように展開されます。
step 0: MACRO(foo,1,2,3,4,5)
step 1: bool ret = foo(1,2,3,4,5 VA_COMMA(1,2,3,4,5) 456)
step 2: bool ret = foo(1,2,3,4,5 GET_6TH_ARG(,1,2,3,4,5,COMMA,COMMA,COMMA,COMMA,) 456)
step 3: bool ret = foo(1,2,3,4,5 5 456)