2010-08-25 5 views
7

Рассмотрим этот макрос:VARIADIC макросы с нулевыми аргументами, и запятые

#define MAKE_TEMPLATE(...) template <typename T, __VA_ARGS__ > 

При использовании с нулевыми аргументами он производит плохой код, поскольку компилятор ожидает идентификатор после запятой. На самом деле препроцессор VC достаточно умен, чтобы удалить запятую, но GCC - нет. Поскольку макросы не могут быть перегружены, это кажется, что это занимает отдельный макрос для этого особого случая, чтобы получить это право, как в:

#define MAKE_TEMPLATE_Z() template <typename T> 

Есть ли способ, чтобы заставить его работать без введения второго макроса?

ответ

9

Нет, поскольку макрокоманда 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__ > 

Во всяком случае, оба также поддерживают VARIADIC шаблоны в режиме C++ 0x, который является гораздо более предпочтительным.

+0

Спасибо. Кстати, это стандартное поведение или вещь gcc? – uj2

+1

@ uj2: Это GCC; стандарт просто запрещает пустые вариационные списки. Кстати, это смешение C99 с C++ в любом случае, поэтому этот код строго нестандартен, если вы не в C++ 0x ... в этом случае вам нужно ... – Potatoswatter

+0

Не против шаблона, это просто игрушечный пример. Как это обязательно 0x, не определяет ли C++ 98/03 переменные макросы? – uj2

1

В случае GCC вы должны написать это:

#define MAKE_TEMPLATE(...) template <typename T, ##__VA_ARGS__ > 

Если __VA_ARGS__ пусто, препроцессор GCC удаляет предшествующую запятую.

0

Прежде всего остерегайтесь того, что переменные макросы не являются частью текущего C++. Кажется, что они будут в следующей версии. На данный момент они соответствуют только если вы программируете на C99.

Как и в случае с переменными макросами с нулевыми аргументами, существуют трюки, позволяющие обнаружить это и макропрограмму вокруг него. Googel для empty macro arguments.