Requires a way to support nested calls in variable arrays with an additional argument. same as C99 compatible
GNU gcc ##extension for operator prevents extension of nested calls, see code below.
#define send(obj, msg, ...) find_method(obj, msg)(obj, ##__VA_ARGS__)
send(0, "+", 1);
find_method(0, "+")(0, 1);
send(send(5, "increment"), "+", 1);
find_method(find_method(5, "increment")(5), "+")(find_method(5, "increment")(5), 1);
send(0, "+", send(5, "increment"));
find_method(0, "+")(0, send(5, "increment"));
I changed the Jens Gustedt solution to place an extra comma, see code below.
Are there any more succinct alternatives?
#define _ARG16( \
_0, _1, _2, _3, _4, \
_5, _6, _7, _8, _9, \
_10, _11, _12, _13, _14, \
_15, ...) _15
#define HAS_COMMA(...) \
_ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define _TRIGGER_PARENTHESIS_(...) ,
#define OPTIONAL_COMMA(...) \
_ISEMPTY( \
\
HAS_COMMA(__VA_ARGS__), \
\
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__), \
\
HAS_COMMA(__VA_ARGS__ ()), \
\
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__ ()) \
)
#define SPACE_SYMBOL
#define COMMA_SYMBOL ,
#define ARG3(_0, _1, _2, ...) _2
#define OPTIONAL_COMMA_FROM(...) ARG3(__VA_ARGS__, SPACE_SYMBOL, COMMA_SYMBOL)
#define PASTE5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
#define _ISEMPTY(_0, _1, _2, _3) \
OPTIONAL_COMMA_FROM(PASTE5(_IS_EMPTY_CASE_, _0, _1, _2, _3))
#define _IS_EMPTY_CASE_0001 ,
#define send(obj, msg, ...) \
find_method(obj, msg)(obj OPTIONAL_COMMA(__VA_ARGS__) __VA_ARGS__)
send(0, "+", 1);
send(send(5, "increment"), "+", 1);
send(0, "+", send(5, "increment"));
Update:
X Walters thanks for the idea.
I did not notice the approach with overload macros in the first place
#define SEND_NO_ARG(obj, msg) find_method(obj, msg)(obj)
#define SEND_ARG(obj, msg, ...) find_method(obj, 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_SELECTOR(...) \
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_SELECTOR(__VA_ARGS__)(__VA_ARGS__)