我为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'而永远不会'1')
谢谢 !
I have these macros defined for visual studio and clang and they both compile fine
#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 is a classic multilevel concat macro
PP_NARG counts the number of macro arguments
PP_LEFT_PAREN and PP_RIGHT_PAREN reduce to '(' and ')'
Is there any way to achieve this with GCC ? ( I tried both macro version with GCC 5.2, both fail to compile because the comma seem to be propagated during macro resolution and removed only at the end of preprocessing, making PP_NARG always reduce to '2' and never '1')
Thanks !
最满意答案
来自doc :
#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)其次,'##'标记粘贴运算符在逗号和变量参数之间具有特殊含义。 如果你写
eprintf ("success!\n") ==> fprintf(stderr, "success!\n");当使用eprintf宏时,省略变量参数,然后删除'##'之前的逗号。 如果传递空参数 ,则不会发生这种情况,如果“##”前面的标记不是逗号,则不会发生这种情况。
上面的解释对于唯一的宏参数是变量参数参数的情况是模棱两可的,因为试图区分根本没有参数是空参数还是缺少参数是没有意义的。 在这种情况下,C99标准很清楚,逗号必须保留 ,但现有的GCC扩展名用于吞下逗号。 因此CPP在符合特定C标准时保留逗号,否则将丢弃。
因此对于
#define declare_func(...) _declare_func ( notused,##__VA_ARGS__ )逗号保留在C标准中,您可以使用-std=gnu99或-std=gnu++11来删除逗号并使用您的工作宏。
演示
要使宏与-std=c++11 ,你必须强制至少有一个参数。
From doc:
#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)Second, the ‘##’ token paste operator has a special meaning when placed between a comma and a variable argument. If you write
eprintf ("success!\n") ==> fprintf(stderr, "success!\n");and the variable argument is left out when the eprintf macro is used, then the comma before the ‘##’ will be deleted. This does not happen if you pass an empty argument, nor does it happen if the token preceding ‘##’ is anything other than a comma.
The above explanation is ambiguous about the case where the only macro parameter is a variable arguments parameter, as it is meaningless to try to distinguish whether no argument at all is an empty argument or a missing argument. In this case the C99 standard is clear that the comma must remain, however the existing GCC extension used to swallow the comma. So CPP retains the comma when conforming to a specific C standard, and drops it otherwise.
So for
#define declare_func(...) _declare_func ( notused,##__VA_ARGS__ )the comma remain in C standard, you may use -std=gnu99 or -std=gnu++11 to drop the comma and have your working macro.
Demo
To make your macro works with -std=c++11, you have so to force to have at least one argument.
更多推荐
发布评论