具有零参数的可变参数宏

发布于 2024-11-05 14:08:49 字数 530 浏览 0 评论 0原文

我正在开发一个调用宏,

#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 not Defined 错误,如果我将称其有效

I am working on a call macro,

#define CALL(f,...) FN(f)->call((ref(new LinkedList()), __VA_ARGS__))

which when called,

CALL(print,2,3,4,5);

adds 2 3 4 5 to the linked list (, is overloaded to do so) and calls print which expects a linked list which works as expected how ever there are some calls which do not require arguments,

CALL(HeapSize);

It still takes a linked list but an empty one, above does not work, I am trying to come up with a macro that woud work with either style?

EDIT: Digging throug gcc docs I found that adding ## before VA_ARGS removes the , when there are no arguments but with that I can not nest macros,

CALL(print,CALL(HeadSize));

this causes CALL not defined error how ever if I separate the the calls it works

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

⒈起吃苦の倖褔 2024-11-12 14:08:49

至于更新的问题,通过使用辅助宏 VA_ARGS
接下来,参数将按预期扩展。

#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))

As for the updated question, by the use of auxiliary macro VA_ARGS like
the following, the arguments will be expanded as expected.

#define VA_ARGS(...) , ##__VA_ARGS__
#define CALL(f,...) FN(f)->call((ref(new LinkedList()) VA_ARGS(__VA_ARGS__)))
吃素的狼 2024-11-12 14:08:49

如果您使用 gcc/g++,有一种方法:

#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))

来自 精细手册:

[...] 如果变量参数被省略或为空,则“##”运算符会导致预处理器删除其前面的逗号。

所以 gcc 有一个专门针对您面临的问题的扩展/黑客。

If you're using gcc/g++ there is a way:

#define CALL(f,...) FN(f)->call((ref(new LinkedList()), ## __VA_ARGS__))

From the fine manual:

[...] if the variable arguments are omitted or empty, the `##' operator causes the preprocessor to remove the comma before it.

So gcc has an extension/hack specifically for the problem you are facing.

琴流音 2024-11-12 14:08:49

__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__)

__VA_OPT__ (c++2a) should be more reliable, eg:
from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0306r2.html

The canonical use case of VA_OPT is for an optional separator:

#define LOG(msg, ...) printf(msg __VA_OPT__(,) __VA_ARGS__)

小矜持 2024-11-12 14:08:49

如果您使用的是 GCC,它有一个扩展名可以吞掉 __VA_ARGS__ 前面的逗号。请参阅:http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros .html

If you are using GCC, it has an extension to swallow up the comma preceding the __VA_ARGS__. See: http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html.

心安伴我暖 2024-11-12 14:08:49

只需将 f 作为 ... 的一部分,然后使用单独的宏在需要 f 的位置提取第一个参数即可。

Simply make f part of the ..., and use a separate macro to extract the first argument where you need f.

烟花易冷人易散 2024-11-12 14:08:49

这些答案的一个共同主题是我们需要针对 GCC 的 hack。一种方法是使用标记粘贴##__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");

优点:

  • 您可以嵌套宏调用,同时具有零个或多个参数。

缺点

  • ##__VA_ARGS__ hack 在标准 C 程序中可能是无害的,因为它们总是至少有一个逗号。 (我还没想过这是否属实)。
  • 根据 @ScootMoonen 的说法,##__VA_ARGS__ hack 是 MSVC 的未记录扩展。

A common theme in these answers is that we need a GCC specific hack. One way is to use the token-paste ##__VAR_ARGS__, but pasted arguments are not macro expanded, which means that macros cannot be nested. But if you are going to do something GCC specific anyway, then why not use the old-fashioned GCC extension:

 #define VARARG_FOO(ZeroOrMoreArgs...) \
     printf("VARARG_FOO: " ZeroOrMoreArgs)

ZeroOrMoreArgs is simply replaced by all the arguments (if any), commas and all. This includes recursive macro expansion.

  • then VARARG_FOO() expands to printf("VARARG_FOO: ")
  • and VARARG_FOO("I iz %d", 42) expands to printf("VARARGFOO: " "I iz %d", 42)

Finally

 #define NEST_ME "I tawt I taw a puddy tat"
 VARARG_FOO("The evil one says %s", NEST_ME); 

will expand to

 printf("VARARG_FOO: " "The evil one says %s", "I tawt I taw a puddy tat");

Pros:

  • You can nest macro invocations, while having zero-or more aguments.

Cons:

  • The ##__VA_ARGS__ hack might be harmless in standard C programs in the case where they always have at least one comma. (I haven't thought about whether this is true or not).
  • According to @ScootMoonen the ##__VA_ARGS__ hack is an undocumented extension to MSVC.
橘和柠 2024-11-12 14:08:49

不幸的是,这无法做到。您需要定义一个单独的宏来执行此调用。

VA_ARGS 没有被替换时,你最终会得到无效的参数,你最终会得到一个浮动的 ,

#define CALL0(f) FN(f)->call((ref(new LinkedList())))

Unfortunately this cannot be done. You will need to define a separate macro to do this call.

As you end up with invalid arguments when VA_ARGS is substituted with nothing you end up with a floating ,

#define CALL0(f) FN(f)->call((ref(new LinkedList())))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文