Могу ли я определить макросы препроцессора C с переменной переменной __VA_ARGS в середине вместо конца? - PullRequest
6 голосов
/ 03 октября 2010

GCC жалуется, если я делаю это:

#define M(obj,met, ..., contents) obj##_##met(const void * self, __VA_ARGS__) { \
   contents \
   }

Дайте мне эти 2 причины:

error: missing ')' in macro parameter list
warning: __VA_ARGS__ can only appear in the expansion of a C99 variadic macro

Очевидно, что макросы типа C99 в стиле C99 ожидают закрывающую скобку сразу после многоточия, фактически требуя, чтобы список параметров Variadic был последним аргументом макроса. Мне нужно, чтобы он был посередине, чтобы создать мою сокращенную запись, описанную в приведенном выше макросе. Поддерживает ли GCC эту функцию, используя другой (не C99) вариационный макрос стиль? Могу ли я подражать, делая это как-нибудь еще? Я не хочу, чтобы список вариаций был в конце, это сделает мои записи запутанными. И я могу использовать только GCC.

Ответы [ 2 ]

9 голосов
/ 03 октября 2010

Нет, ты не можешь.... должен появиться в конце.

Но вы можете определить M как

#define M(obj,met, ...) obj##_##met(const void * self, __VA_ARGS__)

и использовать его как

void M(foo, bar, int x, char y, double z) {
   content;
}
6 голосов
/ 09 мая 2012

Вы должны поставить ... в конце, но используя макросы LAST и POP_LAST, вы можете сохранить тот же порядок аргументов для вашего макроса и определить его следующим образом:

#define M(obj,met, ...) obj##_##met(const void * self, POP_LAST(__VA_ARGS__)) { \
   LAST(__VA_ARGS__) \
   }

Вот как вы можете определить эти макросы:

/* This counts the number of args */
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)

/* This will let macros expand before concating them */
#define PRIMITIVE_CAT(x, y) x ## y
#define CAT(x, y) PRIMITIVE_CAT(x, y)

/* This will pop the last argument off */
#define POP_LAST(...) CAT(POP_LAST_, NARGS(__VA_ARGS__))(__VA_ARGS__)
#define POP_LAST_1(x1)
#define POP_LAST_2(x1, x2) x1
#define POP_LAST_3(x1, x2, x3) x1, x2
#define POP_LAST_4(x1, x2, x3, x4) x1, x2, x3
#define POP_LAST_5(x1, x2, x3, x4, x5) x1, x2, x3, x4
#define POP_LAST_6(x1, x2, x3, x4, x5, x6) x1, x2, x3, x4, x5
#define POP_LAST_7(x1, x2, x3, x4, x5, x6, x7) x1, x2, x3, x4, x5, x6
#define POP_LAST_8(x1, x2, x3, x4, x5, x6, x7, x8) x1, x2, x3, x4, x5, x6, x7

/* This will return the last argument */
#define LAST(...) CAT(LAST_, NARGS(__VA_ARGS__))(__VA_ARGS__)
#define LAST_1(x1) x1
#define LAST_2(x1, x2) x2
#define LAST_3(x1, x2, x3) x3
#define LAST_4(x1, x2, x3, x4) x4
#define LAST_5(x1, x2, x3, x4, x5) x5
#define LAST_6(x1, x2, x3, x4, x5, x6) x6
#define LAST_7(x1, x2, x3, x4, x5, x6, x7) x7
#define LAST_8(x1, x2, x3, x4, x5, x6, x7, x8) x8

Эти макросы будут работать до 8 аргументов.Вы можете легко расширить их, чтобы обрабатывать больше, если хотите.

...