Я создаю новую библиотеку сопоставления с образцом для C ++, и поэтому мне нужно проделать несколько сложных макросов метапрограммирования. Я застрял на следующей ошибке на полдня, и у меня заканчиваются варианты. Я действительно хотел бы, чтобы это работало, все же. Может ли кто-нибудь взглянуть на это?
../../test/macros.cpp:57:16: error: pasting formed ')0', an invalid preprocessing token
ZEN_FOR_EACH(DECLARE_VARS_NUMBERED, foo, bar, baz);
^
../../test/macros.cpp:57:3: error: expected ';' at end of declaration
ZEN_FOR_EACH(DECLARE_VARS_NUMBERED, foo, bar, baz);
^
../../include/zen/macros.h:167:30: note: expanded from macro 'ZEN_FOR_EACH'
#define ZEN_FOR_EACH(m, ...) ZEN_FOR_EACH_WITH(, m, __VA_ARGS__)
^
../../include/zen/macros.h:166:38: note: expanded from macro 'ZEN_FOR_EACH_WITH'
#define ZEN_FOR_EACH_WITH(s, m, ...) ZEN_REPEAT_WITH(s, ZEN_EXPAND(ZEN_VA_LENGTH(__VA_ARGS__)), ZEN_FOR_EACH_IMPL, m, __VA_ARGS__)
^
../../include/zen/macros.h:117:36: note: expanded from macro 'ZEN_REPEAT_WITH'
#define ZEN_REPEAT_WITH(s,n,m,...) ZEN_CONCAT(ZEN_REPEAT_WITH_, n)(s,m,__VA_ARGS__)
^
note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
../../include/zen/macros.h:67:31: note: expanded from macro 'ZEN_CONCAT_IMPL'
#define ZEN_CONCAT_IMPL(a, b) a ## b
^
<scratch space>:3:1: note: expanded from here
ZEN_REPEAT_WITH_3
^
../../include/zen/macros.h:100:38: note: expanded from macro 'ZEN_REPEAT_WITH_3'
#define ZEN_REPEAT_WITH_3(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__) s m(2,__VA_ARGS__)
^
../../test/macros.cpp:57:16: error: pasting formed ')1', an invalid preprocessing token
ZEN_FOR_EACH(DECLARE_VARS_NUMBERED, foo, bar, baz);
^
../../test/macros.cpp:57:3: error: expected ';' at end of declaration
ZEN_FOR_EACH(DECLARE_VARS_NUMBERED, foo, bar, baz);
^
../../include/zen/macros.h:167:30: note: expanded from macro 'ZEN_FOR_EACH'
#define ZEN_FOR_EACH(m, ...) ZEN_FOR_EACH_WITH(, m, __VA_ARGS__)
^
../../include/zen/macros.h:166:38: note: expanded from macro 'ZEN_FOR_EACH_WITH'
#define ZEN_FOR_EACH_WITH(s, m, ...) ZEN_REPEAT_WITH(s, ZEN_EXPAND(ZEN_VA_LENGTH(__VA_ARGS__)), ZEN_FOR_EACH_IMPL, m, __VA_ARGS__)
^
../../include/zen/macros.h:117:36: note: expanded from macro 'ZEN_REPEAT_WITH'
#define ZEN_REPEAT_WITH(s,n,m,...) ZEN_CONCAT(ZEN_REPEAT_WITH_, n)(s,m,__VA_ARGS__)
^
note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
../../include/zen/macros.h:67:31: note: expanded from macro 'ZEN_CONCAT_IMPL'
#define ZEN_CONCAT_IMPL(a, b) a ## b
^
<scratch space>:3:1: note: expanded from here
ZEN_REPEAT_WITH_3
^
../../include/zen/macros.h:100:57: note: expanded from macro 'ZEN_REPEAT_WITH_3'
#define ZEN_REPEAT_WITH_3(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__) s m(2,__VA_ARGS__)
^
../../test/macros.cpp:57:16: error: pasting formed ')2', an invalid preprocessing token
ZEN_FOR_EACH(DECLARE_VARS_NUMBERED, foo, bar, baz);
^
../../test/macros.cpp:57:3: error: expected ';' at end of declaration
ZEN_FOR_EACH(DECLARE_VARS_NUMBERED, foo, bar, baz);
^
../../include/zen/macros.h:167:30: note: expanded from macro 'ZEN_FOR_EACH'
#define ZEN_FOR_EACH(m, ...) ZEN_FOR_EACH_WITH(, m, __VA_ARGS__)
^
../../include/zen/macros.h:166:38: note: expanded from macro 'ZEN_FOR_EACH_WITH'
#define ZEN_FOR_EACH_WITH(s, m, ...) ZEN_REPEAT_WITH(s, ZEN_EXPAND(ZEN_VA_LENGTH(__VA_ARGS__)), ZEN_FOR_EACH_IMPL, m, __VA_ARGS__)
^
../../include/zen/macros.h:117:36: note: expanded from macro 'ZEN_REPEAT_WITH'
#define ZEN_REPEAT_WITH(s,n,m,...) ZEN_CONCAT(ZEN_REPEAT_WITH_, n)(s,m,__VA_ARGS__)
^
note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
../../include/zen/macros.h:67:31: note: expanded from macro 'ZEN_CONCAT_IMPL'
#define ZEN_CONCAT_IMPL(a, b) a ## b
^
<scratch space>:3:1: note: expanded from here
ZEN_REPEAT_WITH_3
^
../../include/zen/macros.h:100:76: note: expanded from macro 'ZEN_REPEAT_WITH_3'
#define ZEN_REPEAT_WITH_3(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__) s m(2,__VA_ARGS__)
Ниже приведено зло, которое я придумал:
#define ZEN_FOR_EACH_IMPL(i, m, ...) m(i, ZEN_GET_VA_ARG(i,__VA_ARGS__))
#define ZEN_FOR_EACH_WITH(s, m, ...) ZEN_REPEAT_WITH(s, ZEN_VA_LENGTH(__VA_ARGS__), ZEN_FOR_EACH_IMPL, m, __VA_ARGS__)
#define ZEN_FOR_EACH(m, ...) ZEN_FOR_EACH_WITH(, m, __VA_ARGS__)
Это должно позволить выполнить индексированный обход списка аргументов. с помощью в качестве обратного вызова другого макроса функции, например, так:
#define DECLARE_VARS_NUMBERED(i, name) int name ## i = 42;
ZEN_FOR_EACH(DECLARE_VARS_NUMBERED, foo, bar, baz);
сгенерирует следующий код:
int foo0 = 42;
int bar1 = 42;
int baz2 = 42;
Этот пример не для того, что я планирую использовать, но этоДолжно быть понятно, что делает макрос.
Это некоторые дополнительные вспомогательные макросы. Большинство из них были сгенерированы автоматически. Их значение должно быть простым. Я протестировал их на нескольких простых сценариях использования, и они работали, как и ожидалось:
#define ZEN_CONCAT(a, b) ZEN_CONCAT_IMPL(a, b)
#define ZEN_CONCAT_IMPL(a, b) a ## b
#define ZEN_REPEAT_WITH_0(s,m,...)
#define ZEN_REPEAT_WITH_1(s,m,...) m(0,__VA_ARGS__)
#define ZEN_REPEAT_WITH_2(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__)
#define ZEN_REPEAT_WITH_3(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__) s m(2,__VA_ARGS__)
#define ZEN_REPEAT_WITH_4(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__) s m(2,__VA_ARGS__) s m(3,__VA_ARGS__)
#define ZEN_REPEAT_WITH_5(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__) s m(2,__VA_ARGS__) s m(3,__VA_ARGS__) s m(4,__VA_ARGS__)
#define ZEN_REPEAT_WITH_6(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__) s m(2,__VA_ARGS__) s m(3,__VA_ARGS__) s m(4,__VA_ARGS__) s m(5,__VA_ARGS__)
#define ZEN_REPEAT_WITH_7(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__) s m(2,__VA_ARGS__) s m(3,__VA_ARGS__) s m(4,__VA_ARGS__) s m(5,__VA_ARGS__) s m(6,__VA_ARGS__)
#define ZEN_REPEAT_WITH_8(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__) s m(2,__VA_ARGS__) s m(3,__VA_ARGS__) s m(4,__VA_ARGS__) s m(5,__VA_ARGS__) s m(6,__VA_ARGS__) s m(7,__VA_ARGS__)
#define ZEN_REPEAT_WITH_9(s,m,...) m(0,__VA_ARGS__) s m(1,__VA_ARGS__) s m(2,__VA_ARGS__) s m(3,__VA_ARGS__) s m(4,__VA_ARGS__) s m(5,__VA_ARGS__) s m(6,__VA_ARGS__) s m(7,__VA_ARGS__) s m(8,__VA_ARGS__)
#define ZEN_REPEAT_WITH(s,n,m,...) ZEN_CONCAT(ZEN_REPEAT_WITH_, n)(s,m,__VA_ARGS__)
#define ZEN_REPEAT(n,m,...) ZEN_REPEAT_WITH(,n,m,__VA_ARGS__)
#define ZEN_GET_VA_ARG_0(arg0,...) arg0
#define ZEN_GET_VA_ARG_1(arg0, arg1,...) arg1
#define ZEN_GET_VA_ARG_2(arg0, arg1, arg2,...) arg2
#define ZEN_GET_VA_ARG_3(arg0, arg1, arg2, arg3,...) arg3
#define ZEN_GET_VA_ARG_4(arg0, arg1, arg2, arg3, arg4,...) arg4
#define ZEN_GET_VA_ARG_5(arg0, arg1, arg2, arg3, arg4, arg5,...) arg5
#define ZEN_GET_VA_ARG_6(arg0, arg1, arg2, arg3, arg4, arg5, arg6,...) arg6
#define ZEN_GET_VA_ARG_7(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7,...) arg7
#define ZEN_GET_VA_ARG_8(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,...) arg8
#define ZEN_GET_VA_ARG_9(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,...) arg9
#define ZEN_GET_VA_ARG(n,...) ZEN_CONCAT(ZEN_GET_VA_ARG_, n)(__VA_ARGS__)
Я действительно не получаю сообщение об ошибке. Я предполагаю, что это связано с тем, что макросы расширяются до того, как они будут переданы, но попытка некоторых модификаций не дала ничего существенного.
Я нашел этот ответ , но яЯ не уверен, как это относится к моему случаю использования.