如何使GCC将'arg,##

编程入门 行业动态 更新时间:2024-10-27 20:26:16
如何使GCC将'arg,## __ VA_ARGS__'减少为'arg'以将其用作单个宏参数?(How to make GCC reduce 'arg,##__VA_ARGS__' to 'arg' to use it as single macro argument?)

我为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宏时,省略变量参数,然后删除'##'之前的逗号。 如果传递空参数 ,则不会发生这种情况,如果“##”前面的标记不是逗号,则不会发生这种情况。

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 ,你必须强制至少有一个参数。

From doc:

Second, the ‘##’ token paste operator has a special meaning when placed between a comma and a variable argument. If you write

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

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.

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

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.

更多推荐

本文发布于:2023-04-27 22:05:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1329027.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:GCC   arg

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!