c++ - 带有 __VA_ARGS__ 的嵌套宏不展开
问题描述
为了获得数量__VA__ARGS__
,我阅读了这个答案并且它有效。但我觉得那PP_NARG_
是多余的,我看不出为什么PP_RSEQ_N
是宏功能。所以我修改代码如下
#include <assert.h>
#define PP_RSEQ_N \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
#define PP_NARG(...) \
PP_ARG_N(__VA_ARGS__,PP_RSEQ_N)
#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
/* Some test cases */
int main() {
assert(PP_NARG(1,2,"yes",!)==4);
}
我收到错误和注释。
main.c:24:33: error: macro "PP_ARG_N" requires 65 arguments, but only 5 given
assert(PP_NARG(1,2,"yes",!)==4);
^
似乎 ,PP_NARG
没有PP_RSEQ_N
展开。但为什么?我知道使用#
and ##
,宏不会被扩展,但事实并非如此。
另外我想知道为什么这个答案PP_NARG_
是必要的,为什么是宏函数,而不是普通的宏(无参数)?PP_RSEQ_N
解决方案
宏调用的本质是宏参数不会在宏调用中展开。标准第 6.10.3.1 节规定了精确的程序。
- 在确定了调用类函数宏的参数后,将进行参数替换。
因此,宏的参数由当时实际存在于令牌流中的逗号分隔,而不管替换的参数可能是什么样的。
一旦收集了参数,宏体中宏参数的使用将被参数替换。在大多数情况下,此时参数会被扩展,但是(如您所见)如果参数用作#
or##
表达式的一部分,则参数不会被宏替换为该 use。此外,宏体中根本不需要使用参数,因此在这种情况下,根本不需要扩展参数。
一旦宏参数被相应的参数替换并且#
和##
运算符被评估,生成的令牌流通过宏处理器传回。在此重新扫描期间,宏主体中使用的任何宏都将被扩展。
现在,作者PP_NARG
实际上想要构造一个宏调用,该宏调用由原始可变参数参数 toPP_NARG
后跟PP_RSEQ_N
. 由于宏参数PP_RSEQ_N
的扩展直到它出现的宏调用的扩展才会发生,因此有必要引入额外的宏扩展级别;该PP_NARG_
宏用于构造对PP_NARG
. (您可以通过完全不使用来避免这种PP_RSEQ_N
情况,而是将倒计时直接放在对 的调用中PP_NARG
。但是有很多理由可以避免这种解决方案;添加额外级别的宏替换更简洁。)
将宏定义为不带参数的类函数宏而不是简单宏的通常原因PP_RSEQ_N
是能够在不扩展宏的情况下传递宏的名称。在此代码段中似乎并非如此,但它可能出现在从中提取代码段的代码的其他地方。
推荐阅读
- powershell - 从另一个使用命名参数和路径中的空格调用一个 powershell 脚本
- awk - 按小时计算列中的值并添加标题
- .net-core - 已发布的自包含 dotnet 核心应用程序的运行时要求
- c# - WPF 应用程序中所有窗口的相同菜单栏或工具栏
- neo4j - 在 Neo4j 中寻找 K 最短路径
- html - 获取最接近标签外文本的值
- assembly - 为什么“sub esp, 96”、“lea eax, [esp+16]”和“mov [esp+4], eax”?(asm intel 语法)
- javascript - 为每个选定的行获取表格的单元格值?
- r - ctree_control 中的错误...未使用的参数...在 R 中
- php - 带有 Apache Mod-Rewrite 的友好 URL