参数为零的可变参数宏
Variadic macros with zero arguments
我正在处理一个调用宏,
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), __VA_ARGS__))
当调用时,
CALL(print,2,3,4,5);
将 2 3 4 5 添加到链表(被重载这样做)并调用 print,它期望一个按预期工作的链表,但有一些不需要参数的调用,
CALL(HeapSize);
它仍然需要一个链表,但一个空的,上面不起作用,我正在尝试想出一个适用于任何一种风格的宏?
编辑:通过 gcc 文档挖掘我发现在 VA_ARGS 之前添加 ## 会删除 ,当没有参数但有了它时,我无法嵌套宏,
CALL(print,CALL(HeadSize));
这会导致 CALL 未定义错误,如果我分离它工作的调用
至于更新的问题,通过使用辅助宏VA_ARGS
,例如接下来,参数将按预期展开。
#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))
如果你使用的是gcc/g++,有一种方法:
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))
从精细手册:
[...]如果变量参数被省略或为空,则"##"运算符会导致预处理器删除其前面的逗号。
因此,gcc 有一个专门针对您面临的问题的扩展/黑客。
__VA_OPT__
(c++2a)应该更可靠,例如:从 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0306r2.html
VA_OPT 的规范用例是可选的分隔符:
#define LOG(msg, ...) printf(msg __VA_OPT__(,) __VA_ARGS__)
如果您使用的是GCC,它有一个扩展名来吞噬__VA_ARGS__
前面的逗号。请参阅:http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html。
只需f
成为...
的一部分,并使用单独的宏在需要f
的地方提取第一个参数。
这些答案的一个共同主题是我们需要一个 GCC 特定的黑客。 一种方法是使用标记粘贴##__VAR_ARGS__
,但粘贴的参数不会宏展开,这意味着宏不能嵌套。 但是,如果您无论如何都要做一些特定于 GCC 的事情,那么为什么不使用老式的 GCC 扩展:
#define VARARG_FOO(ZeroOrMoreArgs...)
printf("VARARG_FOO: " ZeroOrMoreArgs)
ZeroOrMoreArgs
只是被所有参数(如果有的话)、逗号和所有参数所取代。 这包括递归宏扩展。
- 然后
VARARG_FOO()
扩展到printf("VARARG_FOO: ")
VARARG_FOO("I iz %d", 42)
扩展到printf("VARARGFOO: " "I iz %d", 42)
最后
#define NEST_ME "I tawt I taw a puddy tat"
VARARG_FOO("The evil one says %s", NEST_ME);
将扩展到
printf("VARARG_FOO: " "The evil one says %s", "I tawt I taw a puddy tat");
优点:
- 您可以嵌套宏调用,同时具有零个或多个 agument。
缺点:
- 标准 C 程序中可能是无害的,因为它们总是至少有一个逗号。 (我没有想过这是真的还是假的)。
- 根据@ScootMoonen,
##__VA_ARGS__
黑客是MSVC的未记录扩展。
##__VA_ARGS__
黑客在这无法做到。您需要定义一个单独的宏来执行此调用。
当VA_ARGS被替换为任何内容时,您最终会得到无效的参数,因此您最终会得到一个浮动,
#define CALL0(f) FN(f)->call((ref(new LinkedList())))
- 在不传递参数数量且只有3个点的情况下,如何使用变差函数
- 如何使用可变参数模板强制转换每个变体类型
- 关于如何在具有单个参数的变体构造中选择替代方案?
- 调用参数排列不变函数 f(i++, i++)
- 参数归纳与标准::变体
- 模板化回调参数的逆变,如 C# 中的逆变
- 如何在没有参数包的情况下编写变差函数
- 通过具有嵌套类的工厂类获取多个变异类模板参数包
- 获取模板参数的成员变量值列表
- 保留短 lambda 用作函数的中间参数,使用 clang 格式保持不变
- 如何定义变体<x,y,z>提取模板参数的子类型
- 正确对齐内存模板,参数顺序不变
- 递归中不同参数类型的变元模板函数
- 通过函数指针传递给变差函数的参数会更改其值
- 提升预定义为带有参数的全局 lambda 的变体访问者
- 使用可变参数模板参数提升变体访问者
- boost ::变体 - 为什么模板参数比const字符串参数具有更高的优先级
- 将变参数包中的值加载到临时数组中
- 使用额外参数提升变体访客
- 正在将动态数组元素解析为参数?(变音符)