You need some indirection. With C99:
#define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" )
#define INVOKE_NEED3ARGS(...) NEED3ARGS(__VA_ARGS__)
#define MULTIARG() ARG1, ARG2, ARG3
INVOKE_NEED3ARGS( MULTIARG() )
(C99 isn't strictly required; you can replace the variadic macro with a fixed-arity macro.)
If you need to compile your source using Visual C++, you'll need even more indirection (because of a compiler bug):
#define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" )
#define INVOKE_NEED3ARGS_(...) NEED3ARGS __VA_ARGS__
#define INVOKE_NEED3ARGS(...) INVOKE_NEED3ARGS_((__VA_ARGS__))
#define MULTIARG() ARG1, ARG2, ARG3
INVOKE_NEED3ARGS( MULTIARG() )
As for why indirection is needed: a macro argument is not evaluated and macro-replaced until it is substituted into the replacement list. So, when you try NEED3ARGS(MULTIARG())
, MULTIARG()
will not be evaluated until after macro invocation has begun, so it's treated as a single argument.
The INVOKE_NEED3ARGS
macro ensures that its arguments are completely evaluated before NEED3ARGS
is invoked. The __VA_ARGS__
is substituted by the macro-replaced arguments to INVOKE_NEED3ARGS
, which is ARG1, ARG2, ARG3
, then NEED3ARGS
is invoked with those arguments.