Как вы выполняете расширение макроса в #ifdef?


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

#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("%sn", MY_VAR(test));
#endif
3 6

3 ответа:

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

#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_. (Неопределенные идентификаторы заменяются нулем.)

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

Это ответ на ваш обновленный вопрос. Для каждого возможного 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". (Вторая константа здесь удаляет предупреждение gcc:’ hello_test ' определено, но не использованный.)