Я пытаюсь понять, какую версию Boost использует мой код. Я хочу сделать что-то вроде этого:
#error BOOST_VERSION
но препроцессор не расширяет BOOST_VERSION.
Я знаю, что могу распечатать его во время выполнения из программы, и я знаю, что могу посмотреть на вывод препроцессора, чтобы найти ответ. Я чувствую, что способ сделать это во время компиляции может быть полезным.
macros
c-preprocessor
boost-preprocessor
Джим Ханзикер
источник
источник
Ответы:
Я знаю, что прошло много времени после исходного запроса, но это все еще может быть полезно.
Это можно сделать в GCC с помощью оператора строкового преобразования "#", но это требует двух этапов.
Затем значение макроса можно отобразить с помощью:
См. Раздел 3.4 "Строкование" в онлайн-документации gcc.
Как это устроено:
Препроцессор понимает строки в кавычках и обрабатывает их иначе, чем обычный текст. Конкатенация строк является примером такой особой обработки. Прагма сообщения требует аргумента, который является строкой в кавычках. Если у аргумента более одного компонента, тогда все они должны быть строками, чтобы можно было применить конкатенацию строк. Препроцессор никогда не может предположить, что строку без кавычек следует рассматривать так, как если бы она была заключена в кавычки. Если да, то:
не компилируется.
Теперь рассмотрим:
что эквивалентно
Это вызывает предупреждение препроцессора, потому что abc (без кавычек) не может быть объединено с предыдущей строкой.
Теперь рассмотрим преобразование препроцессора в строку (которое когда-то называлось преобразованием в строку, ссылки в документации были изменены, чтобы отразить пересмотренную терминологию. (Оба термина, кстати, одинаково отвратительны. Правильный термин, конечно, stringifaction. Будьте готовы обновить ваши ссылки.)) оператор. Это действует только на аргументы макроса и заменяет нерасширенный аргумент аргументом, заключенным в двойные кавычки. Таким образом:
присвоит одинаковые значения s1 и s2. Если вы запустите gcc -E, вы увидите это на выходе. Возможно, STR лучше было бы назвать как-то вроде ENQUOTE.
Это решает проблему помещения в кавычки элемента, не заключенного в кавычки, проблема в том, что, если аргумент является макросом, макрос не будет расширен. Вот почему нужен второй макрос. XSTR расширяет свой аргумент, затем вызывает STR, чтобы поместить расширенное значение в кавычки.
источник
__IPHONE_9_3
.BOOST_PP_STRINGIZE
кажется отличным решением для C ++, но не для обычного C.Вот мое решение для GNU CPP:
Приведенные выше определения приводят к:
Для переменных «определено как число» , «определено как строка» и «определено, но без значения» они работают нормально. Только для «не определенной» переменной они отображались точно так же, как исходное имя переменной. Вы должны привыкнуть к этому - или, может быть, кто-то может предложить лучшее решение.
источник
DEFINED_INT=(sizeof(MY_STRUCT))
безsizeof
оценки оператора.sizeof
, однако все же любопытно, есть ли какой-то умный способ достижения этого.)#define masks {0xff, 0xaf, 0x0f}
Если вы используете Visual C ++, вы можете использовать
#pragma message
:Редактировать: Спасибо LB за ссылку
Судя по всему, эквивалент GCC (не тестировался):
источник
BOOST_PP_STRINGIZE
что красиво, коротко и копировать / вставлять.Насколько я знаю, "#error" будет печатать только строки, на самом деле вам даже не нужно использовать кавычки .
Вы пробовали писать различный целенаправленно неправильный код с помощью «BOOST_VERSION»? Возможно, что-то вроде "blah [BOOST_VERSION] = foo;" сообщит вам что-то вроде «строковый литерал 1.2.1 не может использоваться как адрес массива». Это не будет красивым сообщением об ошибке, но, по крайней мере, оно покажет вам соответствующее значение. Вы можете поиграть, пока не найдете ошибку компиляции, которая действительно сообщает вам значение.
источник
std::vector<BOOST_VERSION>;
в gcc 4.4.1. Спасибо!Без наддува:
определите тот же макрос снова, и компилятор САМ выдаст предупреждение.
Из предупреждения вы можете увидеть расположение предыдущего определения.
vi предыдущего определения.
источник
__cplusplus
.В Microsoft C / C ++ вы можете использовать встроенные средства
_CRT_STRINGIZE()
для печати констант. Многие из моихstdafx.h
файлов содержат некоторые их комбинации:и выводит что-то вроде этого:
источник
Работает, даже если
preprocess to file
он включен, даже если присутствуют недопустимые токены:источник
Build error: #include expects "FILENAME" or <FILENAME>
. Вздох.'
:*** WARNING C318 IN LINE 2 OF test.c: can't open file '::*/`'
Вы также можете предварительно обработать исходный файл и посмотреть, что оценивает значение препроцессора.
источник
Ты ищешь
Не замечательно, если BOOST_VERSION является строкой, как я предполагал, но также могут быть отдельные целые числа, определенные для основного, вспомогательного номера и номера ревизии.
источник
#if VARIABLE == 123
выражение на лету, и подсветка синтаксиса скажет мне, является ли это значение, которое я думаю, или нет ...Результат препроцессора - это наиболее близкий ответ к вашему запросу.
Я знаю, что вы исключили это (и другие способы), но не знаю почему. У вас есть достаточно конкретная проблема, которую нужно решить, но вы не объяснили, почему какой-либо из «обычных» методов вам не подходит.
источник
Вы можете написать программу, которая распечатает,
BOOST_VERSION
скомпилирует и запустит ее как часть вашей системы сборки. В противном случае, я думаю, тебе не повезло.источник
BOOST_VERSION определяется в файле заголовка boost version.hpp.
источник
Взгляните также на документацию 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 :источник
Вместо #error попробуйте переопределить макрос непосредственно перед его использованием. Компиляция завершится ошибкой, и компилятор предоставит текущее значение, которое, по его мнению, применимо к макросу.
#define BOOST_VERSION blah
источник