#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__)
.
Это не ответ, а просто дополнение к вашему собственному вопросу. –
@JensGustedt Первое поле кода является частичным решением - оно имеет желаемое поведение, но требует '## __ VA_ARGS__', которое является расширением GCC для синтаксиса макроса C99. – augurar
Я это заметил. Немногие исследования по SO могли бы показать вам ответ на этот вопрос. См. Ссылку выше. –