C 可变宏和尾随逗号
我正在尝试用C语言进行对象定向,并希望为符号提供一个语法sugar宏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
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__))