If you are willing to use a slightly clumsy syntax, then you can use Boost.Preprocessor's sequences:
#include <boost/preprocessor.hpp>
#define G(args) BOOST_PP_SEQ_FOR_EACH_I(G_GENF, x, args)
#define G_GENF(r, data, i, elem) \
BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i, 0)) f(elem)
Usage:
G((a))
G((b)(c))
G((d)(e)(f))
Result:
f(a)
f(b) , f(c)
f(d) , f(e) , f(f)
If you do want the G(a, b, c)
syntax, then because macro replacement is not recursive, I think you'll likely need one macro per number of arguments that you are going to pass. You can still delegate to these macros from a single macro used elsewhere in your source, though. Consider:
// Utility for counting the number of args in the __VA_ARGS__ pack:
#define PP_NARGS(...) PP_NARGS2(__VA_ARGS__, PP_NARGS_COUNT())
#define PP_NARGS2(...) PP_NARGS_IMPL(__VA_ARGS__)
#define PP_NARGS_IMPL(x1, x2, x3, N, ...) N
#define PP_NARGS_COUNT() 3, 2, 1, 0, ERROR
// Macros to delegate to concrete, defined-arity implementations:
#define XF(count, ...) XF_IMPL (count, __VA_ARGS__)
#define XF_IMPL(count, ...) XF_ ## count (__VA_ARGS__)
// Defined-arity implementations:
#define XF_1(x1) f(x1)
#define XF_2(x1, x2) f(x1), f(x2)
#define XF_3(x1, x2, x3) f(x1), f(x2), f(x3)
// Delegation macro; this is the only macro you need to call from elsewhere:
#define G(...) XF(PP_NARGS(__VA_ARGS__), __VA_ARGS__)
Usage:
G(a)
G(b, c)
G(d, e, f)
Result:
f(a)
f(b), f(c)
f(d), f(e), f(f)
This could certainly be further generalized, and some preprocessor utilities library might already have some facility to do this, but this demonstrates how it can be done. (I'm not familiar with any C99/C++0x preprocessor libraries, so I can't recommend one.)