预处理器可变参数FOR_EACH宏与MSVC++ 10兼容

Dyl*_*lan 3 c++ foreach visual-c++ variadic-macros

我已经看到一些问题要求变量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), ...,其中x是另一个宏.

Dyl*_*lan 6

现在我已经掌握了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__)
Run Code Online (Sandbox Code Playgroud)

用法示例:

#define callMember(o, f) o.f();
#define callMember_o(f) callMember(o, f)
FOR_EACH(callMember_o, doSomething, doSomethingElse);
Run Code Online (Sandbox Code Playgroud)

是相同的

o.doSomething(); o.doSomethingElse();
Run Code Online (Sandbox Code Playgroud)

此解决方案与链接答案中的解决方案类似,不同之处在于FOR_EACH(what, x, ...)使用一个元素调用时零长度可变参数列表导致伪逗号使FOR_EACH_NARG计数2个参数而不是1个参数,并使用EXPAND宏解决方法.

VC++ 10中的错误是如果__VA_ARGS__在可变参数宏的定义中传递给宏,则在替换为宏之后对其进行求值,从而将多个逗号分隔的参数视为一个.为了解决这个问题,你必须延迟参数评估,直到__VA_ARGS__替换后,通过包装宏调用EXPAND,强制宏调用被评估为字符串,代替__VA_ARGS__这样做.只有在替换为EXPAND被调用的宏之后,可变参数才被替换.

PS如果有人能提出一种方法来紧凑地生成FOR_EACH_N更大值的宏,我将不胜感激N.