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
doubles, you can still say
add(1, 2) and the integer arguments will be converted to
doubles. 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.