Overloading Macro on Number of Arguments

后端 未结 8 1561
离开以前
离开以前 2020-11-22 04:25

I have two macros FOO2 and FOO3:

#define FOO2(x,y) ...
#define FOO3(x,y,z) ...

I want to define a new macro

8条回答
  •  情深已故
    2020-11-22 04:51

    Here is a more general solution:

    // get number of arguments with __NARG__
    #define __NARG__(...)  __NARG_I_(__VA_ARGS__,__RSEQ_N())
    #define __NARG_I_(...) __ARG_N(__VA_ARGS__)
    #define __ARG_N( \
          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
         _61,_62,_63,N,...) N
    #define __RSEQ_N() \
         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
    
    // general definition for any function name
    #define _VFUNC_(name, n) name##n
    #define _VFUNC(name, n) _VFUNC_(name, n)
    #define VFUNC(func, ...) _VFUNC(func, __NARG__(__VA_ARGS__)) (__VA_ARGS__)
    
    // definition for FOO
    #define FOO(...) VFUNC(FOO, __VA_ARGS__)
    

    Define your functions:

    #define FOO2(x, y) ((x) + (y))
    #define FOO3(x, y, z) ((x) + (y) + (z))
    
    // it also works with C functions:
    int FOO4(int a, int b, int c, int d) { return a + b + c + d; }
    

    Now you can use FOO with 2, 3 and 4 arguments:

    FOO(42, 42) // will use makro function FOO2
    FOO(42, 42, 42) // will use makro function FOO3
    FOO(42, 42, 42, 42) // will call FOO4 function
    

    Limitations

    • Only up to 63 arguments (but expandable)
    • Function for no argument only in GCC possible

    Ideas

    Use it for default arguments:

    #define func(...) VFUNC(func, __VA_ARGS__)
    #define func2(a, b) func4(a, b, NULL, NULL)
    #define func3(a, b, c) func4(a, b, c, NULL)
    
    // real function:
    int func4(int a, int b, void* c, void* d) { /* ... */ }
    

    Use it for functions with possible infinite number of arguments:

    #define SUM(...) VFUNC(SUM, __VA_ARGS__)
    #define SUM2(a, b) ((a) + (b))
    #define SUM3(a, b, c) ((a) + (b) + (c))
    #define SUM4(a, b, c) ((a) + (b) + (c) + (d))
    // ...
    

    PS: __NARG__ is copied from Laurent Deniau & Roland Illig here: https://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5?pli=1

提交回复
热议问题