2016-03-01 12 views
0

我已经为Visual Studio和铛定义这些宏,他们都编译罚款如何使GCC将'arg,## __ VA_ARGS__'减少为'arg'以将其用作单个宏参数?

#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'而不是'1')

谢谢!

回答

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让您的宏的作品,你有这么给力至少有一个参数。

+0

你救了我的一天!万分感谢 !做了这项工作..我确实使用-std = C++ 11而不是std = gnu ++ 11。 – Juicebox