Consider this macro:
#define MAKE_TEMPLATE(...) template <typename T, __VA_ARGS__ >
When used with zero arguments it produces bad code since the compiler expects an identifier after the comma. Actually, VC's preprocessor is smart enough to remove the comma, but GCC's isn't. Since macros can't be overloaded, it seems like it takes a separate macro for this special case to get it right, as in:
#define MAKE_TEMPLATE_Z() template <typename T>
Is there any way to make it work without introducing the second macro?
Нет, потому что вызов макроса MAKE_TEMPLATE ()
вообще не имеет нулевых аргументов; у него есть один аргумент, содержащий ноль токенов.
Старые препроцессоры, по-видимому, включая GCC на момент написания этого ответа, иногда интерпретировали пустой список аргументов, как и следовало ожидать, но консенсус сдвинулся в сторону более строгого и узкого расширения, которое более точно соответствует стандарту.
Чтобы ответ, приведенный ниже, работал, определите дополнительный параметр макроса перед многоточием:
#define MAKE_TEMPLATE(UNUSED, ...) template <typename T, ## __VA_ARGS__ >
, а затем всегда ставьте запятую перед первым аргументом, если список не пуст:
MAKE_TEMPLATE(, foo )
Согласно http://gcc.gnu.org/onlinedocs/gcc/Variadic-Macros.html , GCC поддерживает это, но не прозрачно.
Синтаксис:
#define MAKE_TEMPLATE(...) template <typename T, ## __VA_ARGS__ >
В любом случае, оба также поддерживают вариативные шаблоны в режиме C ++ 0x, что намного предпочтительнее.
В случае GCC нужно написать так:
#define MAKE_TEMPLATE(...) template <typename T, ##__VA_ARGS__ >
If __VA_ARGS__
пусто, препроцессор GCC удаляет предыдущую запятую.
Прежде всего имейте в виду, что макросы с переменным числом переменных не являются частью текущей версии C++. Кажется, они будут в следующей версии. На данный момент они соответствуют только в том случае, если вы программируете на C99.
Что касается вариативных макросов с нулевыми аргументами, существуют приемы а-ля boost, чтобы обнаружить это и обработать это макропрограммой. Google для пустых макроаргументов.