Variadic macro and trailing comma

寵の児 提交于 2019-11-30 03:45:50

问题


I am trying to do object-orientation in C and want to have a syntactic sugar macro for the notation

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

into

send(object, method, arg1, arg2)

Unfortunately when a method takes no argument, the trailing comma problem arises

send(object, method)

gives

object->vtable->method(object, )

Is there any portable (no ##__VA_ARGS__ or Visual Studio) way of doing this?

I figured out one but I need to swap the object and the method

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

permits

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

Edit

With the help of two good answers from below I will do it with these macros. It works up to 16 arguments but can easily be extended

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

回答1:


In this answer there is technique explained which should allow you to count the number of parameters and use object and method as the first two arguments.




回答2:


Short answer, yes, it is possible in a portable way.

Long answer: it's complicated, and you probably don't want to implement this yourself. There are ways to count the arguments that a macro receives and then take action according to that number. P99 implements a series of macros that can help you to achieve this. If you'd implement two base macros send_2 and send_more for the two cases you could then implement send as

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

Technically these constructs in P99 have a restriction that they can't handle more than 150 (or so) arguments to send.

BTW, you know that probably, calling a macro send is not really a good idea. Usually people prefer that macros are in all-caps. Also most of the time it is a good idea to have a name prefix that is unique to your library/package, such as AC245_SEND.



来源:https://stackoverflow.com/questions/20818800/variadic-macro-and-trailing-comma

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!