C-preprocessor recursive macro

#define PP_ARG0_(arg0, ...) arg0 #define PP_REST_(arg0, ...) __VA_ARGS__ #define PP_ARG0(args) PP_ARG0_ args #define PP_REST(args) PP_REST_ args #define FUNCTION(name) void name(); #define FUNCTION_TABLE(...) \ FUNCTION(PP_ARG0((__VA_ARGS__))) \ FUNCTION_TABLE(PP_REST((__VA_ARGS__))) \ 

test code:

 FUNCTION_TABLE(f1, f2,f3,testA,testB,testC); 

Obviously, due to the recursive extension, it will only declare void f1(); , and the rest will not be expanded:

 void f1(); FUNCTION_TABLE(f2,f3,testA,testB,testC); 

What trick can I use to achieve recursive expansion in this case? The problem is that I need to support MANY arguments (up to 100), and I absolutely cannot use boost.

+7
source share
2 answers

Here's the answer to if someone 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 the number of arguments, and PP_JOIN is the macro connecting the tokens (i.e. PP_JOIN(a,b) => ab ). You will also need to schedule PP_NARG if you want to process more than 64 arguments.

Now back to the original question. Solution using PP_TRANSFORM :

 #define FUNCTION(name, dummy) void name(); #define FUNCTION_TABLE(...) PP_TRANSFORM(FUNCTION,dummy,__VA_ARGS__) 

if you want to generate C ++ implementation functions, you can use this opaque parameter x PP_TRANSFORM :

 #define FUNCTION_CPP(name, class) void class::name(){} #define FUNCTION_TABLE_CPP(...) PP_TRANSFORM(FUNCTION_CPP,MyClass,__VA_ARGS__) 

All of this works equally well with the GCC and MSVC preprocessors; PP_TRANSFORM_NN does not use __VA_ARGS__ to avoid separate implementations of 100 definitions for GCC and MSVC

+4
source

The simplest solution is to use sequence iteration as follows:

 #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 the varidiac arguments:

 FUNCTION_TABLE((f1)(f2)(f3)(testA)(testB)(testC)) 

This is not only much simpler, but also faster (i.e. faster compilation) than using a recursive solution (like the one you showed or like this one here ).

+8
source

All Articles