Variadic宏和尾随逗号

我试图在C中进行面向对象,并希望为符号设置一个语法糖宏

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

 send(object, method, arg1, arg2) 

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

 send(object, method) 

 object->vtable->method(object, ) 

是否有任何便携式 (没有##__VA_ARGS__或Visual Studio)这样做?

我想出了一个,但我需要交换对象和方法

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

在这个答案中,有一个技术解释,它应该允许您计算参数的数量,并使用objectmethod作为前两个参数。

简短的回答,是的,它可以通过便携方式实现。

答案很长:它很复杂,你可能不想自己实现它。 有一些方法可以计算宏接收的参数,然后根据该数字执行操作。 P99实现了一系列宏,可以帮助您实现这一目标。 如果您为这两种情况实现了两个基本宏send_2send_more ,那么您可以实现send as

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

从技术上讲,P99中的这些结构有一个限制,即它们不能处理超过150个(或左右)的参数send

顺便说一句,你知道,调用宏send可能并不是一个好主意。 通常人们更喜欢宏是全部大写的。 此外,大多数情况下,最好使用您的库/包独有的名称前缀,例如AC245_SEND