如何使GCC减少' arg,## __ VA_ARGS __'到了#arg'将它用作单个宏参数?

时间:2016-03-01 22:43:20

标签: c++ gcc macros

我为visual studio和clang定义了这些宏,它们都编译得很好

#if defined(_MSC_VER)
#   define _declare_func(...) PP_CAT(PP_CAT(_declare_func_, PP_NARG(__VA_ARGS__)),(__VA_ARGS__))
#   define declare_func(...) _declare_func PP_LEFT_PAREN notused,##__VA_ARGS__ PP_RIGHT_PAREN
#else // clang version
#   define _declare_func(...) PP_CAT(_declare_func_, PP_NARG(__VA_ARGS__))(__VA_ARGS__)
#   define declare_func(...) _declare_func ( notused,##__VA_ARGS__ )
#endif

#define _declare_func_1(notused)               void my_function()
#define _declare_func_2(notused, scope)        void scope::my_function()

class MyClass 
{
    declare_func();
};

declare_func(MyClass) { }

PP_CAT是一个经典的多级concat宏

PP_NARG计算宏参数的数量

PP_LEFT_PAREN和PP_RIGHT_PAREN缩减为'('和')'

GCC有没有办法实现这个目标? (我尝试使用GCC 5.2的宏版本,两者都无法编译,因为逗号似乎在宏分辨率期间传播,只在预处理结束时删除,使得PP_NARG总是减少到' 2'并且永远不会&# 39; 1&#39)

谢谢!

1 个答案:

答案 0 :(得分:1)

来自doc

  

其次,'##'标记粘贴运算符在逗号和变量参数之间具有特殊含义。如果你写

 #define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)
  

并且在使用eprintf宏时省略变量参数,然后将删除“##”之前的逗号。如果传递空参数,则不会发生这种情况,如果“##”前面的标记不是逗号,则不会发生这种情况。

 eprintf ("success!\n")
      ==> fprintf(stderr, "success!\n");
  

上述解释对于唯一的宏参数是变量参数参数的情况是模棱两可的,因为尝试区分根本没有参数是空参数还是缺少参数是没有意义的。 在这种情况下,C99标准清楚,逗号必须保持,但现有的GCC扩展名用于吞下逗号。因此,CPP在符合特定C标准时会保留逗号,否则会丢弃它。

所以

#define declare_func(...) _declare_func ( notused,##__VA_ARGS__ )

逗号保留在C标准中,您可以使用-std=gnu99-std=gnu++11删除逗号并使用您的工作宏。

Demo

要使您的宏与-std=c++11一起使用,您必须强制至少有一个参数。