Как расширить вариационные аргументы в макросе?
Я хочу по существу иметь макро-укорочитель.
Макрос, FOO(A,B,C)
следует расширить доdefined(_FOO_A) || defined(_FOO_B) || defined(_FOO_C)
,
Возможно ли это в GCC, используя переменные макро-аргументы и фактически не писать 3 функции (FOO(A)
, FOO(A,B)
, FOO(A,B,C)
)
2 ответа
Невозможно иметь макрос для расширения до чего-то, что содержит defined
ключевое слово:
Если токен
defined
генерируется в результате этого процесса замены или использованияdefined
унарный оператор не соответствует ни одной из двух указанных форм до замены макроса, поведение не определено.
Так что вы не можете сделать это с defined
, Если вы готовы ослабить это ограничение, просто проверив значение FOO_A_
, FOO_B_
... есть способы сделать это с помощью P99. Например, просто сделать логическое или из списка переменных будет
#if P99_ORS(A, B, C)
...
#endif
где P99_ORS
выражение расширяется до
((((A) || (B))) || (C))
и затем оценивается для #if
выражение.
Также были бы способы расширить это сначала в список токенов по своему вкусу, если вы хотите заняться программированием макросов.
#define P00_NAME_X(NAME, X, I) P99_PASTE2(NAME, X)
#define CONDITION(NAME, ...) P99_ORS(P99_FOR(FOO_, P99_NARG(__VA_ARGS__), P00_SEQ, P00_NAME_X, __VA_ARGS__))
такой, что
CONDITION(A, B, C, toto);
будет расширяться до
((((((FOO_A) || (FOO_B))) || (FOO_C))) || (FOO_toto));
Что-то вроде этого?
#include <stdio.h>
#define FOO(A, B, C) (FOO_X(A) || FOO_X(B) || FOO_X(C))
#define FOO_X(x) defined(_FOO_##x)
// just to print it
#define QUOTE(...) QUOTE_AUX(__VA_ARGS__)
#define QUOTE_AUX(...) #__VA_ARGS__
int main(void)
{
puts(QUOTE(FOO(a, b, c)));
}
РЕДАКТИРОВАТЬ: на самом деле это приводит к неопределенному поведению во всех стандартах Си.