I have two functions foo1(a,b) & foo2(a,b,c) and a macro
#define add(a,b) foo(a,b)
I need to re-define macro to accomplish,
1.if add() is called with 2 parameters, then call foo1
- if add() is called with 3 parameters then call foo2
Im new to the option VA_ARGS. How can I do that
If you must use variadic macros, then here is a trick.
#define add(...) _Generic ( &(int[]){__VA_ARGS__}, \
int(*)[2]: add2, \
int(*)[3]: add3) (__VA_ARGS__)
- Have the macro create a compound literal array. The size of this array will depend on the number of arguments.
- Grab the address of the compound literal, to get an array pointer type.
- Let
_Generic
check which type you got, then call the proper function based on that.
This is 100% standard C and also type safe.
Demo:
#include <stdio.h>
#define add(...) _Generic ( &(int[]){__VA_ARGS__}, \
int(*)[2]: add2, \
int(*)[3]: add3) (__VA_ARGS__)
int add2 (int a, int b);
int add3 (int a, int b, int c);
int main (void)
{
printf("%d\n", add(1, 2));
printf("%d\n", add(1, 2, 3));
//printf("%d\n", add(1, 2, 3, 4)); Compiler error for this.
}
int add2 (int a, int b)
{
return a + b;
}
int add3 (int a, int b, int c)
{
return a + b + c;
}
That usual trick for counting arguments may be adapted for this:
#define ADD_EXPAND(...) \
ADD_EXPAND_(__VA_ARGS__, EXPAND_ADD_FUNCS())
#define ADD_EXPAND_(...) \
EXPAND_ADD_SEL_FUNC(__VA_ARGS__)
#define EXPAND_ADD_SEL_FUNC(first_, second_, third_, func, ...) func
#define EXPAND_ADD_FUNCS() foo2, foo, dummy
#define add(...) ADD_EXPAND(__VA_ARGS__)(__VA_ARGS__)
Once you plow through the boiler plate, it basically just involves placing all the arguments in a line, with the function tokens after them, and seeing which function stands out. That's what EXPAND_ADD_SEL_FUNC
does.
You can see it live on coliru.
But I'll reiterate what we told you in comments. This is likely to be a sub-par solution to a proper function. I haven't tested it thoroughly, so breakage is easily possible. Use at your own risk.
If you just want to distinguish between two functions, the following works:
#define ADD(_1, _2, _3, X, ...) X
#define add(...) ADD(__VA_ARGS__, add3, add2, 0)(__VA_ARGS__)
The auxiliary macro ADD
always picks the fourth argument:
add(a, b) --> ADD(a, b, add3, add2, 0) --> add2
add(a, b, c) --> ADD(a, b, c, add3, add2, 0) --> add3
The drawback is that you get quite cryptic error messages when you don't supply two or three arguments to the function.
The advantage over variadic functions is that you get type safety. For example if your functions operate on double
s, you can still say add(1, 2)
and the integer arguments will be converted to double
s. And variadic functions require some additional information on the number of actual arguments, so that's not a feasible solution here, unless you specify the number of summands in the function.
Addendum: I've changed the add
macro so that it doesn't pass an empty variadic list to ADD
. Some compilers allow empty lists, but it isn't standard C.