为什么这个可变参数计数宏会因VC ++而失败?

时间:2011-04-03 15:28:11

标签: c++ visual-studio-2010 visual-c++ c-preprocessor

我得到了以下实现来获取可变参数宏中的参数数量(目前限制为16个参数)。但是,对于VS2010,无论传递多少个参数,输出始终为1With GCC,输出是正确的,让我得出结论,我一定错过了MSVC(10)特有的东西。

#define PP_NARGS(...) \
    _xPP_NARGS_IMPL(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)

#define _xPP_NARGS_IMPL(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,N,...) N

int main(){
    int i = PP_NARGS(A,V,C,X,Y,Z);

    std::cout << i;

    std::cin.get();
    return 0;
}

所以,问题就像标题所述,任何帮助都会受到赞赏。

3 个答案:

答案 0 :(得分:23)

以下解决方法是否有帮助?

#define EXPAND(x) x
#define PP_NARGS(...) \
    EXPAND(_xPP_NARGS_IMPL(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))

我认为你的宏没有特别错,但是 MSVC的__VA_ARGS__扩展似乎与C99的行为不同。

答案 1 :(得分:1)

问题似乎是Visual Studio在将传递到后续宏之后展开__VA_ARGS__ ,而gcc在传递之前将其扩展。

在您的情况下,PP_NARGS(A,V,C,X,Y,Z)A,V,C,X,Y,Z绑定到__VA_ARGS__,然后将其作为一个整体传递给_xPP_NARGS_IMPL

作为测试,运行:

#define PP_NARGS(...) \
    _xPP_NARGS_IMPL(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)

#define _xPP_NARGS_IMPL(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,N,...) \
  (std::cout << #x1 << std::endl, N) 

int main() {
  int i = PP_NARGS(A, V, C, X, Y, Z);
  std::cout << i;
  return 0;
}

您会在屏幕上看到A, V, C, X, Y, Z,而不仅仅是A正如您所期望的那样。

正如Ise Wisteria所建议的那样,可能的解决方案是通过以下方式强制扩展:

#define EXPAND(x) x
#define PP_NARGS(...) \
    EXPAND(_xPP_NARGS_IMPL(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))

答案 2 :(得分:-9)

__VA_ARGS__是C99语言功能 VC ++不是C99编译器 做数学。

这就像尝试使用Scheme编译器编译Pascal并发现奇怪它不适用于'开始/结束'对。

我不知道C ++和Visual Studio在这一切中的表现如何。