Как я могу показать значение #define во время компиляции?



Я пытаюсь выяснить, какая версия Boost мой код думает, что он использует. Я хочу сделать что-то вроде этого:



#error BOOST_VERSION



но препроцессор не расширяет BOOST_VERSION.



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

716   12  

12 ответов:

Если вы используете Visual C++, вы можете использовать #pragma message:

#include <boost/preprocessor/stringize.hpp>
#pragma message("BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION))

Edit: спасибо LB за ссылку

по-видимому, эквивалент GCC (не тестируется):

#pragma message "BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION)

BOOST_PP_STRINGIZE кажется отличным решением для C++, но не для обычного C.

вот мое решение для GNU CPP:

/* Some test definition here */
#define DEFINED_BUT_NO_VALUE
#define DEFINED_INT 3
#define DEFINED_STR "ABC"

/* definition to expand macro then apply to pragma message */
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define VAR_NAME_VALUE(var) #var "="  VALUE(var)

/* Some example here */
#pragma message(VAR_NAME_VALUE(NOT_DEFINED))
#pragma message(VAR_NAME_VALUE(DEFINED_BUT_NO_VALUE))
#pragma message(VAR_NAME_VALUE(DEFINED_INT))
#pragma message(VAR_NAME_VALUE(DEFINED_STR))

выше определения приводят к:

test.c:10:9: note: #pragma message: NOT_DEFINED=NOT_DEFINED
test.c:11:9: note: #pragma message: DEFINED_BUT_NO_VALUE=
test.c:12:9: note: #pragma message: DEFINED_INT=3
test.c:13:9: note: #pragma message: DEFINED_STR="ABC"

на "определить как interger", "определяется как строка" и "определено, но не имеет значения" переменные , они работают просто отлично. Только для "не определен" переменная, они отображаются точно так же, как и исходное имя переменной. Ты должен ... привыкли к этому-или, может быть, кто-то может обеспечить лучшее решение.

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

Это можно сделать в GCC с помощью оператора stringify "#", но для этого требуется два этапа.

#define XSTR(x) STR(x)
#define STR(x) #x

значение макроса может быть отображено с помощью:

#pragma message "The value of ABC: " XSTR(ABC)

см.: 3.4 Строкование в электронной документации gcc.

насколько я знаю, '# error ' будет печатать только строки, на самом деле вам даже не нужно использовать кавычки.

вы пробовали писать различные целенаправленно неверный код с помощью "BOOST_VERSION"? Возможно, что-то вроде "blah[BOOST_VERSION] = foo;" скажет вам что-то вроде "строковый литерал 1.2.1 не может использоваться в качестве адреса массива". Это не будет довольно сообщение об ошибке, но по крайней мере он покажет вам соответствующее значение. Вы можете играть вокруг, пока не найдете ошибку компиляции это говорит вам о ценности.

без наддува :

  1. определите тот же макрос снова и компилятор сам даст предупреждение.

  2. из предупреждения вы можете увидеть расположение предыдущего определения.

  3. vi файл предыдущего определения .

ambarish@axiom:~/cpp$ g++ shiftOper.cpp
shiftOper.cpp:7:1: warning: "LINUX_VERSION_CODE" redefined
shiftOper.cpp:6:1: warning: this is the location of the previous definition

#define LINUX_VERSION_CODE 265216
#define LINUX_VERSION_CODE 666

int main ()
{

}

вы также можете предварительно обработать исходный файл и посмотреть, что значение препроцессора вычисляет.

#define a <::BOOST_VERSION>
#include a
MSVC2015: неустранимая ошибка C1083: не удается открыть файл include:':: 106200' : нет такого файла или каталога

работает, даже если preprocess to file включен, даже если присутствуют недопустимые маркеры:

#define a <::'*/`#>
#include a
MSVC2015: неустранимая ошибка C1083: не удается открыть файл include: '::'*/`#': нет такого файла или каталога
версии gcc4.x: предупреждение: отсутствует завершающий символ [- Winvalid-pp-token]
#определите a<::>

глядя на результат работы препроцессора, ближе всего к ответу, который вы просите.

Я знаю, что вы исключили это (и другие способы), но я не уверен, почему. У вас есть достаточно конкретная проблема для решения, но вы не объяснили, почему ни один из "нормальных" методов не работает хорошо для вас.

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

ищите

#if BOOST_VERSION != "1.2"
#error "Bad version"
#endif

Не очень хорошо, если BOOST_VERSION является строкой, как я предполагал, но также могут быть отдельные целые числа, определенные для основных, второстепенных и номеров версий.

BOOST_VERSION определяется в версии файла заголовка boost.ТЭЦ.

взгляните также на документацию Boost, касающуюся того, как вы используете макрос:

в отношении BOOST_VERSION, от http://www.boost.org/doc/libs/1_37_0/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.boost_helper_macros:

описывает номер версии boost в Формата XXYYZZ, такие, что: (BOOST_VERSION % 100) - это суб-минор версия,((BOOST_VERSION / 100) % 1000) является второстепенной версией, и (BOOST_VERSION / 100000) главные версия.

Comments

    Ничего не найдено.