C 可变宏和尾随逗号

C 可变宏和尾随逗号,c,c-preprocessor,variadic-macros,C,C Preprocessor,Variadic Macros,我正在尝试用C语言进行对象定向,并希望为符号提供一个语法sugar宏 object->vtable->method(object, arg1, arg2) 进入 不幸的是,当一个方法不带参数时,后面的逗号问题就会出现 send(object, method) 给予 是否有任何便携式(无####(无)(无)(无)(无)VA(无)(无)ARGS(无 我找到了一个,但我需要交换对象和方法 #define FIRST_ARG_(N, ...) N #define FIRST_ARG(ar

我正在尝试用C语言进行对象定向,并希望为符号提供一个语法sugar宏

object->vtable->method(object, arg1, arg2)
进入

不幸的是,当一个方法不带参数时,后面的逗号问题就会出现

send(object, method)
给予

是否有任何便携式(无
####(无
)(无)(无)(无)VA(无)(无)ARGS(无

我找到了一个,但我需要交换对象和方法

#define FIRST_ARG_(N, ...) N
#define FIRST_ARG(args) FIRST_ARG_(args)
#define send(msg, ...) \
 FIRST_ARG(__VA_ARGS__)->vtable->msg(__VA_ARGS__)
许可证

send(method, object)
send(method, object, arg1, arg2)
编辑

在下面两个好答案的帮助下,我将用这些宏来完成它。它最多可使用16个参数,但很容易扩展

#define SEND_NO_ARG(obj, msg) obj->vtable->msg(obj)
#define SEND_ARG(obj, msg, ...) obj->vtable->msg(obj, __VA_ARGS__)

#define GET_18TH_ARG(arg1, arg2, arg3, arg4, arg5, \
    arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, \
    arg16, arg17, arg18, ...) arg18
#define SEND_MACRO_CHOOSER(...) \
    GET_18TH_ARG(__VA_ARGS__, \
            SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
            SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
            SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
            SEND_NO_ARG, )

#define SEND(...) SEND_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)

在本文中,介绍了一种技术,该技术应允许您计算参数的数量,并使用
对象
方法
作为前两个参数。

简短回答,是的,可以以便携方式进行

详细回答:这很复杂,您可能不想自己实现它。有几种方法可以计算宏接收到的参数,然后根据这些参数采取行动。实现一系列可以帮助您实现这一目标的宏。如果要为这两种情况实现两个基本宏
send_2
send_more
,则可以按如下方式实现
send

#define send(...)                     \
 P99_IF_LT(P99_NARG(__VA_ARGS__), 3)  \
 (send_2(__VA_ARGS__))                \
 (send_more(__VA_ARGS__))
从技术上讲,P99中的这些构造有一个限制,即它们不能处理超过150个(大约150个)的参数来发送


顺便说一句,您可能知道,调用宏
send
并不是一个好主意。通常人们更喜欢宏都是大写的。大多数情况下,最好使用库/包特有的名称前缀,例如
AC245\u SEND

不,没有。这就是这些扩展存在的原因:-(
#定义发送(方法、对象等)对象->vtable->方法(对象、参数)
不可移植?不,它是一个GCC扩展。这里有一个关于面向对象C源代码方法的堆栈溢出问题和答案。可能重复的答案不是好答案,因为它没有提供内联的实际答案。如果链接的答案被删除了怎么办?如果p99消失了,这个答案对我有什么帮助?没有我们甚至没有提供关于计算参数的基本方法的信息
#define SEND_NO_ARG(obj, msg) obj->vtable->msg(obj)
#define SEND_ARG(obj, msg, ...) obj->vtable->msg(obj, __VA_ARGS__)

#define GET_18TH_ARG(arg1, arg2, arg3, arg4, arg5, \
    arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, \
    arg16, arg17, arg18, ...) arg18
#define SEND_MACRO_CHOOSER(...) \
    GET_18TH_ARG(__VA_ARGS__, \
            SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
            SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
            SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
            SEND_NO_ARG, )

#define SEND(...) SEND_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
#define send(...)                     \
 P99_IF_LT(P99_NARG(__VA_ARGS__), 3)  \
 (send_2(__VA_ARGS__))                \
 (send_more(__VA_ARGS__))