9

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__)
5
  • 2
    No, there isn't. That's why those extensions exist. :-( Commented Dec 28, 2013 at 20:06
  • #define send(method, object, ...) object->vtable->method(object,##__VA_ARGS__) is not portable ? Commented Dec 28, 2013 at 20:19
  • No it's a GCC extension Commented Dec 28, 2013 at 20:23
  • Here is a stack overflow question and answers on the subject of approaches for object oriented C source code. stackoverflow.com/questions/351733/… Commented Dec 28, 2013 at 21:54
  • Possible duplicate of Optional Parameters with C++ Macros Commented Jul 13, 2018 at 19:14

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

How does this answer help me if p99 goes away? It doesn't even provide information about the fundamental approach to counting argument
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.

1 Comment

This is not good answer as it doesn't provide the actual answer inline. What if the linked answer gets deleted?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.