Variadic recursive preprocessor macros - is it possible?

前端 未结 6 881
一生所求
一生所求 2020-11-28 07:11

I\'ve run into a little theoretical problem. In a piece of code I\'m maintaining there\'s a set of macros like

#define MAX_OF_2(a, b)       (a) > (b) ? (a         


        
6条回答
  •  情歌与酒
    2020-11-28 08:01

    It's possible to write a macro that evaluates to the number of arguments it's called with. (I couldn't find a link to the place where I first saw it.) So you could write MAX_OF_N() that would work as you'd like, but you'd still need all the numbered macros up until some limit:

    #define MAX_OF_1(a)         (a)         
    #define MAX_OF_2(a,b)       max(a, b)
    
    #define MAX_OF_3(a,...)    MAX_OF_2(a,MAX_OF_2(__VA_ARGS__))
    #define MAX_OF_4(a,...)    MAX_OF_2(a,MAX_OF_3(__VA_ARGS__))
    #define MAX_OF_5(a,...)    MAX_OF_2(a,MAX_OF_4(__VA_ARGS__))
    ...
    #define MAX_OF_64(a,...)   MAX_OF_2(a,MAX_OF_63(__VA_ARGS__))
    
    // NUM_ARGS(...) evaluates to the literal number of the passed-in arguments.
    #define _NUM_ARGS2(X,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_ARGS2(0, __VA_ARGS__ ,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,0)
    
    #define _MAX_OF_N3(N, ...) MAX_OF_ ## N(__VA_ARGS__)
    #define _MAX_OF_N2(N, ...) _MAX_OF_N3(N, __VA_ARGS__)
    #define MAX_OF_N(...)      _MAX_OF_N2(NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
    

    Now MAX_OF_N(a,b,c,d,e) will evaluate to max(a, max(b, max(c, max(d, e)))). (I've tested on gcc 4.2.1.)

    Note that it's critical that the base case (MAX_OF_2) doesn't repeat its arguments more than once in the expansion (which is why I put max in this example). Otherwise, you'd be doubling the length of the expansion for every level, so you can imagine what will happen with 64 arguments :)

提交回复
热议问题