Макрос FOR_EACH препроцессора Variadic, совместимый с MSVC ++ 10

Я видел несколько вопросов, спрашивающих о вариации FOR_EACH макро. Однако, к сожалению, предоставленные ответы несовместимы с VC ++ 10, так как он расширяет __VA_ARGS __ в качестве одного аргумента при передаче другому макросу. Пожалуйста, кто-нибудь может предоставить C ++ 11-совместимую (следовательно, совместимую с версией) версию, которая все еще работает с VC ++ 10. Возможно, используя «обходной путь», который часто упоминается, #define EXPAND(x) xОднако я не знаю, где это поставить, чтобы получить, например, последнюю обобщенную часть этот ответ работать в VC ++ 10.

Чтобы уточнить, предполагаемое поведение для FOR_EACH(x, a, b, ...) производить x(a) x(b), ...где х другой макрос.

2

Решение

Теперь, точно поняв, как работает ошибка компилятора VC ++ 10, я смог сам создать такой макрос, основываясь на последней части этот ответ.

#define EXPAND(x) x
#define FOR_EACH_1(what, x, ...) what(x)
#define FOR_EACH_2(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_1(what,  __VA_ARGS__))
#define FOR_EACH_3(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_2(what, __VA_ARGS__))
#define FOR_EACH_4(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_3(what,  __VA_ARGS__))
#define FOR_EACH_5(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_4(what,  __VA_ARGS__))
#define FOR_EACH_6(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_5(what,  __VA_ARGS__))
#define FOR_EACH_7(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_6(what,  __VA_ARGS__))
#define FOR_EACH_8(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_7(what,  __VA_ARGS__))
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) EXPAND(FOR_EACH_ARG_N(__VA_ARGS__))
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
#define CONCATENATE(x,y) x##y
#define FOR_EACH_(N, what, ...) EXPAND(CONCATENATE(FOR_EACH_, N)(what, __VA_ARGS__))
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)

Пример использования:

#define callMember(o, f) o.f();
#define callMember_o(f) callMember(o, f)
FOR_EACH(callMember_o, doSomething, doSomethingElse);

такой же как

o.doSomething(); o.doSomethingElse();

Это решение аналогично решению в связанном ответе, за исключением того, что список аргументов переменной длины нулевой длины в FOR_EACH(what, x, ...) при вызове с одним элементом возникла ложная запятая, которая заставляет FOR_EACH_NARG считать 2 аргумента вместо 1 аргумента, и EXPAND макрос обходной путь используется.

Ошибка в VC ++ 10 заключается в том, что если __VA_ARGS__ передается макросу в определении макроса variadic, он оценивается после подстановки в макрос, что приводит к тому, что несколько разделенных запятыми аргументов рассматриваются как один. Чтобы обойти это, вы должны отложить оценку аргумента до __VA_ARGS__ подставляется, оборачивая вызов макроса в EXPAND, заставляя вызов макроса оцениваться как строку, подставляя __VA_ARGS__ сделать это. Только после замены в EXPAND это вызываемый макрос, к которому точка вариативных аргументов уже подставлена.

Постскриптум Я был бы признателен, если кто-нибудь может предложить метод для компактного производства FOR_EACH_N макросы для гораздо больших значений N,

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]