Overloading Macro on Number of Arguments Overloading Macro on Number of Arguments c c

Overloading Macro on Number of Arguments


Simple as:

#define GET_MACRO(_1,_2,_3,NAME,...) NAME#define FOO(...) GET_MACRO(__VA_ARGS__, FOO3, FOO2)(__VA_ARGS__)

So if you have these macros:

FOO(World, !)         # expands to FOO2(World, !)FOO(foo,bar,baz)      # expands to FOO3(foo,bar,baz)

If you want a fourth one:

#define GET_MACRO(_1,_2,_3,_4,NAME,...) NAME#define FOO(...) GET_MACRO(__VA_ARGS__, FOO4, FOO3, FOO2)(__VA_ARGS__)FOO(a,b,c,d)          # expeands to FOO4(a,b,c,d)

Naturally, if you define FOO2, FOO3 and FOO4, the output will be replaced by those of the defined macros.


To add on to netcoder's answer, you CAN in fact do this with a 0-argument macro, with the help of the GCC ##__VA_ARGS__ extension:

#define GET_MACRO(_0, _1, _2, NAME, ...) NAME#define FOO(...) GET_MACRO(_0, ##__VA_ARGS__, FOO2, FOO1, FOO0)(__VA_ARGS__)


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 FOO2FOO(42, 42, 42) // will use makro function FOO3FOO(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