我知道我可以这样做:
#define MACRO(api, ...) \
bool ret = api(123, ##__VA_ARGS__);
这只是一个例子,它是更复杂的解决方案的一部分。关键是我需要将可变数量的参数追加到前123个。 如果没有参数传递给MACRO,##会使编译器在123参数后删除逗号。
但现在我想向api添加参数,如下:
#define MACRO(api, ...) \
bool ret = api(__VA_ARGS__##, 456);
诺坎多。一种解决方案是使用两个宏,MACRO和MACRO_V,并使_V版本不处理任何参数。但有没有办法让它适用于一个宏?
答案 0 :(得分:17)
是的,你可以。以下内容最多支持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__
):之前的一个空参数(不必为空 - 它被抛弃)和四个逗号以及之后的空参数。 / p>
这六个或更多个参数传递给GET_6TH_ARG
,顾名思义,它扩展到第六个参数。所有其他参数都被丢弃了。
因此,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)
答案 1 :(得分:4)
没有。允许在第一种情况下工作的##
的行为是GCC扩展(C99不允许变量参数部分为空),它特别适用于左侧带逗号的情况和{ {1}}在右边。参见例如http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Variadic-Macros.html#Variadic-Macros(位于页面底部)。
答案 2 :(得分:3)
嗯,我认为这可能是这样的:
#define NO_FIRST(first, ...) __VA_ARGS__
#define DO_APPEND_LAST(last, ...) NO_FIRST(__VA_ARGS__, last)
#define MACRO(api, ...) bool ret = api(DO_APPEND_LAST(456, dummy, ##__VA_ARGS__));
没有检查,但是应该在最新的VS和gcc中工作。