我为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)
谢谢!
答案 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
删除逗号并使用您的工作宏。
要使您的宏与-std=c++11
一起使用,您必须强制至少有一个参数。