#define call_foo(...) \
do { \
int first; \
int second; \
int third; \
(__VA_ARGS__); \
foo(first, second, third); \
} while (0)
....
int main(void) {
call_foo(first=9, third=5, second=3);
}
Получение возвращаемых значений без затруднений.
Это позволит вам делать очень глупые вещи (которые я ненавижу), такие как указание значений по умолчанию для ваших аргументов:
#define call_foo(...) \
do { \
int first = default_first; \
int second; \
int third; \
(__VA_ARGS__); \
foo(first, second, third); \
} while (0)
Это не удастся, если вы сделаете:
int first = 9;
call_foo(first=first, third=5, second=3);
потому что в расширении макроса first=first
будет означать инициализацию локального first
с самим собой. Я думал о попытке обойти это с помощью конкатенации препроцессора, но это становится более сложным. Вам нужно будет указать то же количество параметров макроса, что и для параметров функции.
#define call_foo(x, y , z) \
do { \
int call_foo_first; \
int call_foo_second; \
int call_foo_third; \
call_foo_##x; \
call_foo_##y; \
call_foo_##z; \
foo(call_foo_first, call_foo_second, call_foo_third); \
} while (0)
Строка call_foo_##x;
превратится в call_foo_first=first;
, если вызывается в предыдущем примере, поэтому у каждого символа есть свое уникальное имя.
Это делает трюк с аргументом по умолчанию более неловким, потому что вам нужно указать что-то, чтобы заполнить это место в списке аргументов макроса.
Если макрос был определен с аргументом по умолчанию для first
, тогда:
call_foo(first, third=7, second=8);
Это вынуждает вас перечислять все параметры (или, по крайней мере, что-то, что приводит к допустимому C - вы могли бы перечислить секунду дважды, но вы могли бы сделать это в любом случае), чтобы использовать этот макрос.
Я думаю, что вы должны иметь возможность расширить последнюю версию этого для переменных макросов / функций, перечисленных в качестве аргумента переменной, но необязательные параметры все равно должны быть переданы в конце списка, и вам придется использовать все обязательные места, прежде чем вы получите необязательные аргументы.