Обнаружение присутствия или отсутствия аргументов в макросе C

Как можно определить макрос C IFARGS(YES, NO, ...) , так что IFARGS без дополнительных аргументов вызывает NO , а IFARGS с одним или несколькими аргументами дает YES ?

У меня есть ответ с использованием GCC (см. Ниже), но я предпочел бы один для C99, если это возможно (или доказательство его невозможности).

В C99 можно определить, является ли аргумент макроса пустым, но делает это устойчивым против всех коэффициентов, которые могут появляться в этом аргументе (аргументы, которые сами расширяются, содержат () и т. Д.) Сложно. Мой пакет макросов P99 реализует такую ​​вещь, поэтому вам не придется слишком беспокоиться. При этом ваш макрос может быть реализован как

 #define IFARGS(YES, NO, ...) P99_IF_EMPTY(__VA_ARGS__)(YES(__VA__ARGS__))(NO()) 

Как видно из названия, P99 работает только с функциями C99.

 #define GET(_0, _1) _0 // Return the first of two arguments #define GET_(_0, _1) _1 // Return the second of two arguments #define JOIN(_0, _1) _0 ## _1 // Concatenate two arguments #define EJOIN(_0, _1) JOIN(_0, _1) // Expand macros and concatenate #define FIRST(_, ...) _ // Truncate everything after first comma #define EFIRST(_) FIRST(_) // Expand argument and pass to FIRST #define REST(_0, ...) __VA_ARGS__ // Remove everything before first comma #define GET_GET(...) \ EJOIN(GET, EFIRST(REST(,,##__VA_ARGS__ _))) // Branch between GET and GET_ #define IFARGS(YES, NO, ...) GET_GET(__VA_ARGS__)(YES, NO) 

Заметим, что если бы это было возможно на C99, тогда можно было бы имитировать ##__VA_ARGS__ , например:

 #define PREPEND_COMMA(...) , __VA_ARGS__ #define NO_COMMA() #define PREPEND_COMMA_IF_NONEMPTY(...) IFARGS(PREPEND_COMMA, NO_COMMA, __VA_ARGS__)(__VA_ARGS__) 

Тогда любой экземпляр , ##__VA_ARGS__ можно заменить PREPEND_COMMA_IF_NONEMPTY(__VA_ARGS__) .