Как вы выполняете расширение макроса в #ifdef? - PullRequest
6 голосов
/ 24 апреля 2010

У меня есть довольно общий код, который использует макросы препроцессора для добавления определенного префикса в другие макросы. Это очень упрощенный пример того, что происходит:

#define MY_VAR(x) prefix_##x

"prefix_" на самом деле определен в другом месте, поэтому он будет отличаться при каждом включении файла. Это работает хорошо, но теперь у меня есть код, который я хотел бы пропустить, если один из токенов не существует, но это не работает:

#if defined MY_VAR(hello)

Я хочу, чтобы это расширилось:

#ifdef prefix_hello

Но я не могу понять, как. Мне нужно использовать макрос MY_VAR () для расширения, поэтому я не могу просто жестко закодировать имя. (Это на самом деле для некоторого кода тестирования, один и тот же код каждый раз включается с разным префиксом для тестирования группы классов, и я хочу пропустить пару тестов для нескольких классов.)

Возможно ли это с препроцессором C ++?

Обновление:

Вот некоторый полускомпилируемый код, чтобы продемонстрировать проблему дальше: (чтобы не вдавливать его в комментарии ниже)

#define PREFIX hello

#define DO_COMBINE(p, x)  p ## _ ## x
#define COMBINE(p, x)     DO_COMBINE(p, x)
#define MY_VAR(x)         COMBINE(PREFIX, x)

// MY_VAR(test) should evaluate to hello_test

#define hello_test "blah blah"

// This doesn't work
#ifdef MY_VAR(test)
  printf("%s\n", MY_VAR(test));
#endif

Ответы [ 3 ]

3 голосов
/ 24 апреля 2010

Есть ли в вашей программе больше, чем описывает этот вопрос? Директива

#define MY_VAR(x) prefix_##x

определяет ровно один идентификатор препроцессора. Звонок

blah ^&* blah MY_VAR(hello) bleh <>? bleh

просто входит в один конец препроцессора, а выходит в другой, ничего не определяя.

Без какого-либо другого волшебства вы не можете ожидать, что препроцессор запомнит, какие аргументы были переданы в какие макросы в течение предыдущего исходного кода.

Вы можете сделать что-то вроде

#define prefix_test 1
#if MY_VAR(test) == 1
#undef prefix_test // optional, "be clean"
...
#endif
#undef prefix_test

, чтобы узнать, имеет ли префикс в данный момент конкретное значение prefix_. (Неопределенные идентификаторы заменяются на ноль.)

2 голосов
/ 24 апреля 2010

Я думаю, вы достигли уровня, на котором препроцессор больше не будет его резать; это действительно довольно просто. Рассматривали ли вы вместо этого использование шаблонов? (Конечно, если они имеют значение для вашей проблемы.)

0 голосов
/ 03 мая 2010

Это ответ на ваш обновленный вопрос. Для каждого возможного hello_test, после любой возможности #define hello_test "бла-бла", добавьте строки:

#ifndef hello_test
#define hello_test (char*)0
#endif

Затем измените свой тест на:

if (MY_VAR(test))
    printf("%s\n", MY_VAR(test));

Или, в качестве альтернативы, перед всеми #define ... "бла-бла", добавить строку (и):

static const char * const MY_VAR(test);

для всех возможных значений MY_VAR и test. Это позволит избежать жесткого кодирования "hello_test". (Второе const здесь удаляет предупреждение gcc: hello_test 'определено, но не используется.)

...