C-preprocessor recursive macro
Here's the answer in case somebody wants to do the same.
#define _PP_0(_1, ...) _1 // (a,b,c,d) => a
#define _PP_X(_1, ...) (__VA_ARGS__) // (a,b,c,d) => (b,c,d)
//for each a in __VA_ARGS__ do f(a,x)
//where x is some parameter passed to PP_TRANSFORM
#define PP_TRANSFORM(f,x,...) \
PP_JOIN(PP_TRANSFORM_,PP_NARG(__VA_ARGS__))(f,x,(__VA_ARGS__))
#define PP_TRANSFORM_0(...)
#define PP_TRANSFORM_1( f,x,a) f(_PP_0 a,x) PP_TRANSFORM_0( f,x,_PP_X a)
#define PP_TRANSFORM_2( f,x,a) f(_PP_0 a,x) PP_TRANSFORM_1( f,x,_PP_X a)
...
#define PP_TRANSFORM_51(f,x,a) f(_PP_0 a,x) PP_TRANSFORM_50( f,x,_PP_X a)
...
#define PP_TRANSFORM_99(f,x,a) f(_PP_0 a,x) PP_TRANSFORM_98(f,x,_PP_X a)
#define PP_TRANSFORM_100(f,x,a)f(_PP_0 a,x) PP_TRANSFORM_99(f,x,_PP_X a)
where PP_NARG
is the macro that counts number of arguments and PP_JOIN
is the macro that joins tokens (that is PP_JOIN(a,b) => ab
). You'll also need to patch that PP_NARG
if you want to be able to process more than 64 arguments.
Now, back to the original question. Solution using the PP_TRANSFORM
is:
#define FUNCTION(name, dummy) void name();
#define FUNCTION_TABLE(...) PP_TRANSFORM(FUNCTION,dummy,__VA_ARGS__)
if you want to generate c++ implementation functions then you can use that opaque x parameter of PP_TRANSFORM
:
#define FUNCTION_CPP(name, class) void class::name(){}
#define FUNCTION_TABLE_CPP(...) PP_TRANSFORM(FUNCTION_CPP,MyClass,__VA_ARGS__)
All this works equally well with GCC and MSVC preprocessors; PP_TRANSFORM_NN doesn't use __VA_ARGS__
to avoid separate implementations of 100 defines for GCC and MSVC
The simplest solution is to use sequence iteration like this:
#define CAT(x, y) PRIMITIVE_CAT(x, y)
#define PRIMITIVE_CAT(x, y) x ## y
#define FUNCTION(name) void name();
#define FUNCTION_TABLE(seq) CAT(FUNCTION_TABLE_1 seq, _END)
#define FUNCTION_TABLE_1(x) FUNCTION(x) FUNCTION_TABLE_2
#define FUNCTION_TABLE_2(x) FUNCTION(x) FUNCTION_TABLE_1
#define FUNCTION_TABLE_1_END
#define FUNCTION_TABLE_2_END
Then you call FUNCTION_TABLE
with a preprocessor sequence instead of varidiac arguments:
FUNCTION_TABLE((f1)(f2)(f3)(testA)(testB)(testC))
Not only is this much simpler, its also faster(ie faster compilation) than using the recursive solution(like the one you've shown or like this one here).