Reputation: 508
I was wandering if there is a way to define a variadic macro that handles its last argument in a different way.
For example, can I define a macro that prints a custom separator after every argument except for the last one?
i.e. how to define MACRO:
MACRO(a, lot, of, bars)
In order to produce this output:
a|lot|of|bars
(EDIT: it was pointed out to me by the comments that the case of ,
as separator is trivial)
Upvotes: 0
Views: 227
Reputation: 70382
You can apply the macro argument counting trick. For up to five macro arguments (the original answer supported 4 macro arguments, so you can view the diff to see how to extend the macro for additional arguments):
#define MACRO(...) MACRO_X(__VA_ARGS__,5,4,3,2,1)(__VA_ARGS__)
#define MACRO_X(_5,_4,_3,_2,_1,X,...) MACRO_##X
#define MACRO_5(X,...) X|MACRO_4(__VA_ARGS__)
#define MACRO_4(X,...) X|MACRO_3(__VA_ARGS__)
#define MACRO_3(X,...) X|MACRO_2(__VA_ARGS__)
#define MACRO_2(X,...) X|MACRO_1(__VA_ARGS__)
#define MACRO_1(X,...) X
To create a string, you can use the "stringify" operator:
#define STR2(X) STR(X)
#define STR(X) #X
So:
puts(STR2(MACRO(a,lot,of,bars)));
Upvotes: 3
Reputation: 141544
If the output does not need to be stringised, then you can produce an equivalent expression relatively simply:
#define MACRO(...) BIGMACRO(__VA_ARGS__,0,0,0,0,0,0,0,0)
#define BIGMACRO(a0,a1,a2,a3,a4,a5,a6,a7,...) a0|a1|a2|a3|a4|a5|a6|a7
so MACRO(a,lot,of,bars)
expands to a|lot|of|bars|0|0|0|0
, which has the same type and value as a|lot|of|bars
.
Upvotes: 2