Генерация ошибки, если флажок boolean macro не определен

У меня есть несколько файлов конфигурации, каждый из которых содержит определение некоторого логического макроса, который должен быть установлен в 0 или 1. Затем в моем коде я проверяю значение такого макроса, чтобы решить, какую часть кода активировать. Теперь идет сложная часть: я хочу быть уверенным, что заголовок, содержащий определение моего макроса, был включен.

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

//in the configuration header file
#define FOO 1

//in a cpp file
#if FOO  //I would like this to generate an error if I forgot to include the header file
#pragma message "Hello"
#else
#pragma message "world!"
#endif

Можно ли добиться такого поведения? Как?

Чтобы уточнить, я не спрашиваю, как генерировать ошибку, если макрос не определен, но если можно преобразовать строку #if FOO чтобы в то же время он проверял логическое значение и генерировал ошибку, если FOO не определен.

Дело в том, что разработчики должны знать, что их код должен содержать

SPECIAL_MACRO(FOO)

которые в то же время проверяют логическое значение FOO, как если бы это был оператор #if FOO, и не позволяли им забыть включение заголовка, определяющего FOO.

Ответ 1

Коллеги (привет Хартмут, Курт), которые поддерживали большую базу кода, которая была тщательно сконфигурирована с #define точно #define с той же проблемой. Простая неправильная орфография, возможно, в файле make, может привести к тонким ошибкам, которые трудно отследить. Их решение: используйте макросы функций! В

#if SOME_COND()
 // ...
#endif

компилятор жалуется, если SOME_COND() не определен, в отличие от простого SOME_COND, который будет заменен на 0, если не определено. Мне это нравится, потому что он может использоваться для переноса нескольких значений без загромождения кода с помощью дополнительных #ifdef s.

Ответ 2

Принятый ответ использования функций-макросов хорош, но если вы хотите сохранить обычные макросы - и по-прежнему использовать значение FOO, если оно определено, и генерировать ошибку, иначе вы могли бы сделать:

#if FOO / defined(FOO)
#else
#endif

Если FOO не определен, он вызывает целочисленное деление на ноль.

Ответ 3

Как насчет использования препроцессора -Wundef gcc? Это приведет к появлению предупреждения, которое можно легко переключить на ошибку с -Werror=undef.

Ответ 4

Я думаю, может решить вашу проблему в простом сложном решении. Я изменяю свой код, как показано ниже, и мой код понимает, что header.h не существует и показывает ошибку для меня.

  #if FOO == 1 
    #pragma message "Hello"
#elif FOO == 2 
    #pragma message "world!"
#else
    throw std::invalid_argument("Header didn't add to project");
#endif

только вам нужно изменить свое начальное значение для Foo. потому что компилятор активирует Foo == 0, когда он не находит FOO, вы не должны использовать значение 0 для вашей конфигурации. вы должны оставить ноль для ситуации отсутствия заголовка. Вместо этого вы должны использовать значения больше нуля (1, 2, 3,...).

Foo == 0 ситуация отсутствия.

Foo == 1 Конфигурация 1.

Foo == 2 Конфигурация 2.

,

,

,