Если вы хотите использовать слегка неуклюжий синтаксис, вы можете использовать последовательности Boost.Preprocessor:
#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)
Использование:
G((a))
G((b)(c))
G((d)(e)(f))
Результат:
f(a)
f(b) , f(c)
f(d) , f(e) , f(f)
Если вам нужен синтаксис G(a, b, c)
, то, поскольку замена макросов не является рекурсивной, я думаю, вам, вероятно, понадобится один макрос на число аргументов, которые вы собираетесь передать.Вы все еще можете делегировать эти макросы из одного макроса, используемого в другом месте вашего источника.Рассмотрим:
// 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__)
Использование:
G(a)
G(b, c)
G(d, e, f)
Результат:
f(a)
f(b), f(c)
f(d), f(e), f(f)
Это, безусловно, можно обобщить, и некоторые библиотеки утилит препроцессора уже могут иметь некоторые средствасделать это, но это демонстрирует, как это можно сделать.(Я не знаком ни с какими библиотеками препроцессора C99 / C ++ 0x, поэтому не могу порекомендовать одну из них.)