You can use various recursive macro techniques to do things with variadic macros. For example, you can define a NUM_ARGS
macro that counts the number of arguments to a variadic macro:
#define _NUM_ARGS(X100, X99, X98, X97, X96, X95, X94, X93, X92, X91, X90, X89, X88, X87, X86, X85, X84, X83, X82, X81, X80, X79, X78, X77, X76, X75, X74, X73, X72, X71, X70, X69, X68, X67, X66, X65, X64, X63, X62, X61, X60, X59, X58, X57, X56, X55, X54, X53, X52, X51, X50, X49, X48, X47, X46, X45, X44, X43, X42, X41, X40, X39, X38, X37, X36, X35, X34, X33, X32, X31, X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, X16, X15, X14, X13, X12, X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1, N, ...) N
#define NUM_ARGS(...) _NUM_ARGS(__VA_ARGS__, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
Then with that, you can write a FOREACH
macro that expands another macro for each element of a list:
#define EXPAND(X) X
#define FIRSTARG(X, ...) (X)
#define RESTARGS(X, ...) (__VA_ARGS__)
#define FOREACH(MACRO, LIST) FOREACH_(NUM_ARGS LIST, MACRO, LIST)
#define FOREACH_(N, M, LIST) FOREACH__(N, M, LIST)
#define FOREACH__(N, M, LIST) FOREACH_##N(M, LIST)
#define FOREACH_1(M, LIST) M LIST
#define FOREACH_2(M, LIST) EXPAND(M FIRSTARG LIST) FOREACH_1(M, RESTARGS LIST)
#define FOREACH_3(M, LIST) EXPAND(M FIRSTARG LIST) FOREACH_2(M, RESTARGS LIST)
:
Which will in turn allow you to to define your macro that stringifies each of its arguments:
#define STRINGIFY(X) #X
#define MY_VARIADIC_MACRO(...) FOREACH(STRINGIFY, (__VA_ARGS__))
Okay, I didn't mean to answer my own question here, but I've come up with a decent solution that is somewhat of a combination of Mark Wilkins answer and the example I gave in the question.
It is possible to stringify the entire set variadic set, which then includes the delimiting commas in the string. Here's a quick example:
#define MY_VARIADIC_MACRO(X...) printf(#X)
Using the above macro shows you that the entire set of arguments passed to the macro gets stringified.
Then you can then define a function to tokenize these arguments using the delimiting comma, thereby getting the set of tokenized strings by using the variadic macro:
#define MY_VARIADIC_MACRO(X...) tokenize_my_arguments(#X)
Then there's actually no longer the dependency of having the variadic macro call a variadic function and I can iterate nicely through my array of constant C strings rather than iterating through va_arg.
* New Stuff from Edit Follows *
Per Tim's comment, here's the details of the solution. Please forgive any errors since it was done in haste and I had to port from what I'm working on. Also, it's not meant to be copy/paste solution since it only outputs the stringification of the arguments to demonstrate POC, but should be sufficient enough to demonstrate the functionality.
Although this solution requires some run time computation, variadic macros often times call variadic functions and requires iterating through va_args, so the iteration takes place in finding the tokens, although a bit of performance is probably sacrificed. However, for maintainability, versatility, and ease of implementation, this seems to be the best option at the moment:
#define VARIADIC_STRINGIFY(_ARGUMENTS_TO_STRINGIFY...) Variadic_Stringification_Without_Variadic_Function(#_ARGUMENTS_TO_STRINGIFY)
void Variadic_Stringification_Without_Variadic_Function (const char* _stringified_arguments)
{
strcpy(converted_arguments, _stringified_arguments);
for(char* token = strtok(converted_arguments, ","); token != 0x0; token = strtok(0x0, ","))
std::cout << token << std::endl;
}