MSVC ++可变宏扩展 [英] MSVC++ variadic macro expansion

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

问题描述

所以我有一个宏在GCC工作得很好,但不是在微软的C ++编译器。我希望有人可能知道一个解决方法,或者也许可以解释为什么它的行为这种方式。

So I've got a macro that works nicely in GCC, but not in Microsoft's C++ Compiler. I'm hoping somebody might know of a workaround, or perhaps can explain to me why it behaves this way.

我确定这个宏并不是标准,但它真的会帮助我。

I'm sure this macro isn't exactly "standard", but it would really help me out.

以下是宏的功能示例:

#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)

#define FULLY_EXPANDED(count, ...) \
  MAC ## count (__VA_ARGS__)

#define SEMI_EXPANDED(count, ...) FULLY_EXPANDED(count, __VA_ARGS__)

#define EXPAND_THESE(...) SEMI_EXPANDED(VA_NARGS(__VA_ARGS__), __VA_ARGS__)

#define ACTUAL_MACRO(x) parent->GetProperty<x>();
#define MAC1(a) ACTUAL_MACRO(a)
#define MAC2(a,b) MAC1(a) ACTUAL_MACRO(b)
#define MAC3(a,b,c) MAC2(a,b) ACTUAL_MACRO(c)
#define MAC4(a,b,c,d) MAC3(a,b,c) ACTUAL_MACRO(d)
#define MAC5(a,b,c,d,e) MAC4(a,b,c,d) ACTUAL_MACRO(e)



<我可以使用这个宏:

Here is how I might use this macro:

struct MyStructure
{
  void Foo()
  {
    EXPAND_THESE(Property1, Property2, Property3, Property4)
  }

  Base * parent;
}

GCC扩展上述内容的方法如下:

Here's how GCC expands the above:

struct MyStructure
{
  void Foo()
  {
    parent->GetProperty<Property1>(); 
    parent->GetProperty<Property2>(); 
    parent->GetProperty<Property3>(); 
    parent->GetProperty<Property4>();
  }

  Base * parent;
}

但是Microsoft由于某种原因将我的__VA_ARGS__扩展为一个参数:

But Microsoft for some reason expands all my __VA_ARGS__ as one argument:

struct MyStructure
{
  void Foo()
  {
    parent->GetProperty<Property1, Property2, Property3, Property4>();
  }

  Base * parent;
}

有没有人知道为什么会这样?有没有一些技巧,我可以拉微软扩大这像GCC?也许折腾一对额外的对括号?

Does anybody know why this is? Is there some trick I can pull to get Microsoft to expand this like GCC? Maybe toss in a couple extra pairs of parentheses?

这样的宏真的可以帮助我更换一堆胶水代码,但因为这个问题,我不能移动到我的VS项目。任何帮助将非常感谢!

Macros like this could really help me out in replacing a bunch of "glue" code, but because of this problem, I can't move it into my VS project. Any help would be greatly appreciated!

谢谢。

推荐答案

巧合的是,我偶然遇到了这个问题,经过足够的努力,我发现了一个解决方案我自己的目的。该错误是MSVC将 __ VA_ARGS __ 视为参数列表中的单个标记。但是你可以通过不直接在宏调用参数列表中使用它来解决这个问题。 此评论建议开始您的问题的答案:

Coincidentally, I happened to run into this problem just today, and after enough effort I think I've found a solution for my own purposes. The bug is MSVC treats __VA_ARGS__ as a single token in argument lists. But you can work around this by not using it directly within a macro call argument list. This comment suggests the start of an answer to your problems:

#define VA_NARGS(...) VA_NUM_ARGS_IMPL_((__VA_ARGS__, 5,4,3,2,1))
#define VA_NARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NARGS_IMPL(_1,_2,_3,_4,_5,N,...) N

但是,我怀疑你可能遇到的问题,确保完全扩展到你想要的实际N不是 VA_NARGS_IMPL(arg1,arg2,5,4,3,2,1)。我发现我的代码(看起来像你的)不得不改变以扩展 MAC ## code all作为一个单位,然后必须单独结合参数列表。下面是我为我找到的代码:

But then I suspect you'll likely run into the issue of making sure that gets fully expanded to the actual "N" you want, and not to VA_NARGS_IMPL (arg1, arg2, 5, 4, 3, 2, 1), say. I found that my code (which looked like yours) had to change to expand MAC##code all as one unit, and then that had to be separately combined with the argument list. Here's the code that I found worked for me:

#define ASSERT_HELPER1(expr) singleArgumentExpansion(expr)
#define ASSERT_HELPER2(expr, explain) \
   twoArgumentExpansion(expr, explain)

/*
 * Count the number of arguments passed to ASSERT, very carefully
 * tiptoeing around an MSVC bug where it improperly expands __VA_ARGS__ as a
 * single token in argument lists.  See these URLs for details:
 *
 *   http://connect.microsoft.com/VisualStudio/feedback/details/380090/variadic-macro-replacement
 *   http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/#comment-644
 */
#define COUNT_ASSERT_ARGS_IMPL2(_1, _2, count, ...) \
   count
#define COUNT_ASSERT_ARGS_IMPL(args) \
   COUNT_ASSERT_ARGS_IMPL2 args
#define COUNT_ASSERT_ARGS(...) \
   COUNT_ASSERT_ARGS_IMPL((__VA_ARGS__, 2, 1, 0))
 /* Pick the right helper macro to invoke. */
#define ASSERT_CHOOSE_HELPER2(count) ASSERT_HELPER##count
#define ASSERT_CHOOSE_HELPER1(count) ASSERT_CHOOSE_HELPER2(count)
#define ASSERT_CHOOSE_HELPER(count) ASSERT_CHOOSE_HELPER1(count)
 /* The actual macro. */
#define ASSERT_GLUE(x, y) x y
#define ASSERT(...) \
   ASSERT_GLUE(ASSERT_CHOOSE_HELPER(COUNT_ASSERT_ARGS(__VA_ARGS__)), \
               (__VA_ARGS__))

int foo()
{
  ASSERT(one); // singleArgumentExpansion(one)
  ASSERT(two, "foopy"); // twoArgumentExpansion(two, "foopy")
}

几个小时后解决我自己的问题,然后去完全解决你的,我很抱歉说。 :-)但我认为这足以让你的东西工作,有一点工作。

My mind is too much mush after a few hours solving my own issues to then go and completely solve yours, I'm sorry to say. :-) But I think this is enough to get you to something that works, with a little work.

这篇关于MSVC ++可变宏扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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