预处理器可变参数FOR_EACH宏与MSVC ++ 10兼容 [英] Preprocessor variadic FOR_EACH macro compatible with MSVC++10

查看:204
本文介绍了预处理器可变参数FOR_EACH宏与MSVC ++ 10兼容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到了一些问题,要求对变量 FOR_EACH 宏进行修改。不幸的是,所提供的答案与VC ++ 10不兼容,因为它将__VA_ARGS __作为一个参数扩展到另一个宏时。请有人可以提供一个C ++ 11兼容(从而向前兼容)版本,仍然适用于VC + + 10。也许使用经常提到的解决方法, #define EXPAND(x)x ,但是我不知道为了得到这个,后者广义的一部分这个答案在VC ++ 10中工作。



为了澄清,预期的行为是用于产生 x(a)x的 FOR_EACH(x,a,b,...) (b),... ,其中x是另一个宏。

解决方案

如何在VC ++ 10编译器的错误工作,我能够拿出这样一个宏我自己,根据后面的这个答案

  #define EXPAND(x)x 
#define FOR_EACH_1(what,x,.. (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(wh at,__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, 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(什么,...)FOR_EACH_(FOR_EACH_NARG(__ VA_ARGS__),什么,__VA_ARGS__)

用法示例: / p>

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


$ b $

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

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



在VC ++ 10中的错误是,如果 __ VA_ARGS __ 被传递给一个可变宏的定义中的一个宏,它被置换到宏中后被计算,导致多个逗号分隔的参数被视为一个。为了解决这个问题,你必须延迟参数评估,直到 __ VA_ARGS __ 被取代,将宏调用包装在 EXPAND 中,迫使宏调用被评估为一个字符串,用 __ VA_ARGS __ 来代替。只有在代入 EXPAND 之后,被调用的宏,可变参数才被替换。我将不胜感激,如果任何人都可以提出一个方法来紧凑地生成 FOR_EACH_N 宏的更大的值 N p>

I've seen a few questions asking for a variation on a variadic FOR_EACH macro. However unfortunately the answers provided are incompatible with VC++10 due to it expanding __VA_ARGS __ as one argument when passed to another macro. Please could someone provide a C++11 compliant (thus forward-compatible) version that still works with VC++10. Perhaps using the "workaround" that is often mentioned, #define EXPAND(x) x, however I don't know where to put this in order to get, for example, the latter generalised part of this answer to work in VC++10.

To clarify, the intended behaviour is for FOR_EACH(x, a, b, ...) to produce x(a) x(b), ..., where x is another macro.

解决方案

Having now grasped exactly how the VC++10 compiler bug works, I was able to come up with such a macro myself, based on the latter part of this answer.

#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__)

Example usage:

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

is the same as

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

This solution is similar to that in the linked answer, except that the zero length variadic argument list in FOR_EACH(what, x, ...) when called with one element caused a spurious comma that makes FOR_EACH_NARG count 2 arguments instead of 1 argument, and the EXPAND macro workaround is used.

The bug in VC++10 is that if __VA_ARGS__ is passed to a macro within the definition of a variadic macro, it is evaluated after substitution into the macro, causing multiple comma separated arguments to be treated as one. To get around this you must delay argument evaluation until after __VA_ARGS__ is substituted, by wrapping the macro call in EXPAND, forcing the macro call to be evaluated as a string, substituting __VA_ARGS__ to do so. Only after the substitution into EXPAND is the macro called, by which point the variadic arguments are already substituted.

P.S. I would be grateful if anyone can suggest a method for compactly producing FOR_EACH_N macros for much larger values of N.

这篇关于预处理器可变参数FOR_EACH宏与MSVC ++ 10兼容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆