Неожиданное предопределенное поведение макроса при вставке токенов - PullRequest
1 голос
/ 15 августа 2010

Следующее (тест с gcc -E blah.c):

#define UNUSED(type) type UNUSED_ ## __COUNTER__
UNUSED(char const *)
UNUSED(int)

Формирует:

char const * UNUSED__COUNTER__
int UNUSED__COUNTER__

Я ожидаю:

char const * UNUSED0
int UNUSED1

Я пытался вызвать другой макрос, заключив аргументы в скобки, но безрезультатно. Если я не вставлю токены, это будет работать нормально. В документации конкретно упоминается использование __COUNTER__ при вставке токена.

Что я делаю не так?

Ответы [ 3 ]

1 голос
/ 15 августа 2010

__COUNTER__ был введен только в GCC 4.3 - если вы используете более раннюю версию, макрос просто не определен.В этом случае, возможно, стоит рассмотреть макрос Boost.PPs BOOST_PP_COUNTER.

В более новых версиях GCC вам все равно нужен другой подход к объединению, так как ## предотвращает расширение его аргументов,Таким образом, вы должны сначала развернуть их, прежде чем использовать ##:

#define CAT(a, b) CAT_I(a, b)
#define CAT_I(a, b) CAT_II(a ## b)
#define CAT_II(x) x
#define UNUSED(type) type CAT(UNUSED_, __COUNTER__)

Если вы уже используете Boost, BOOST_PP_CAT() предоставляет вам ту же функциональность.

1 голос
/ 15 августа 2010

Экспериментируя с gcc 4.4, это работает:

#define UNUSED(type) UNUSED_(type, __COUNTER__)
#define UNUSED_(type, counter) UNUSED__(type, counter)
#define UNUSED__(type, counter) type UNUSED_ ## counter
UNUSED(char const *)
UNUSED(int)

Но это не сработает, если я уберу хотя бы один уровень промежуточных звеньев.

0 голосов
/ 15 августа 2010

Я полагаю, вы должны "дважды развернуть" его:

#define STR(x)    #x
#define UNUSED(type) type UNUSED_ ## STR(__COUNTER__)
UNUSED(char const *) 
UNUSED(int) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...