Могу ли я переопределить макрос С++ и определить его обратно?
Я использую в своем коде как библиотеку JUCE, так и ряд заголовков Boost. Juce определяет "T" как макрос (стон), а Boost часто использует "T" в своих определениях шаблонов. В результате, если вы каким-то образом включаете заголовки JUCE перед заголовками Boost, препроцессор расширяет макрос JUCE в коде Boost, а затем компилятор безнадежно теряется.
Сохранение моих включений в правильном порядке в большинстве случаев непросто, но может быть сложно, если у вас есть класс JUCE, который включает некоторые другие классы, а где-то в цепочке один файл включает Boost, и если какой-либо из файлы, прежде чем понадобится JUCE, включите в себя проблемы.
Моя первоначальная надежда на фиксацию этого была в
#undef T
перед тем, как включить в Boost. Но проблема в том, что если я не переопределяю его, тогда другой код путается, что "T" не объявлен.
Тогда я подумал, что, возможно, я мог бы сделать круговой трюк #define, например:
// some includes up here
#define ___T___ T
#undef T
// include boost headers here
#define T ___T___
#undef ___T___
Уродливо, но я думал, что это может сработать.
К сожалению нет. Я получаю ошибки в местах с использованием "T" в качестве макроса, который
'___T___' was not declared in this scope.
Есть ли способ, чтобы эти две библиотеки работали надежно вместе?
Ответы
Ответ 1
Как отметил greyfade, трюк ___T___
не работает, потому что препроцессор - довольно простое существо. Альтернативный подход заключается в использовании директив pragma:
// juice includes here
#pragma push_macro("T")
#undef T
// include boost headers here
#pragma pop_macro("T")
Это должно работать в MSVС++, а GCC добавила поддержку pop_macro
и push_macro
для совместимости с ним. Технически это зависит от реализации, но я не думаю, что существует стандартный способ временного подавления определения.
Ответ 2
Можете ли вы обернуть библиотеку оскорблений в другой include и уловить #define T внутри?
например:
JUICE_wrapper.h:
#include "juice.h"
#undef T
main.cpp:
#include "JUICE_wrapper.h"
#include "boost.h"
rest of code....
Ответ 3
Тогда я подумал, что, возможно, я мог бы сделать круговой трюк #define, например:
Препроцессор C не работает таким образом. Символы препроцессора не определены в том же смысле, что символ имеет значение, когда, например, вы определяете функцию.
Это может помочь подумать о препроцессоре как о механизме замены текста. Когда символ определен, он обрабатывается как прямое текстовое замещение до конца файла или до него undefined. Его значение не хранится нигде и поэтому не может быть скопировано. Поэтому единственный способ восстановить определение T
после того, как вы #undef
ed, это полностью воспроизвести его значение в новой #define
позже в вашем коде.
Лучшее, что вы можете сделать, это просто не использовать Boost или просить разработчиков JUCE не использовать T
в качестве макроса. (Или, в худшем случае, исправьте это сами, изменив имя макроса.)