Могу ли я переопределить макрос C++ и определить его обратно?
В моем коде я использую библиотеку 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.
Есть ли способ заставить эти две библиотеки надежно работать вместе?
3 ответа
Как указал Greyfade, ваш ___T___
Трюк не работает, потому что препроцессор - довольно простое существо. Альтернативный подход заключается в использовании прагматических директив:
// juice includes here
#pragma push_macro("T")
#undef T
// include boost headers here
#pragma pop_macro("T")
Это должно работать в MSVC++ и GCC добавил поддержку pop_macro
а также push_macro
для совместимости с ним. Технически это зависит от реализации, но я не думаю, что есть стандартный способ временного подавления определения.
Можете ли вы обернуть оскорбительную библиотеку в другой файл include и перехватить #define T внутри?
например:
JUICE_wrapper.h:
#include "juice.h"
#undef T
main.cpp:
#include "JUICE_wrapper.h"
#include "boost.h"
rest of code....
Затем я подумал, что, возможно, я мог бы сделать несколько круговых трюков #define, например, так:
Препроцессор C не работает таким образом. Символы препроцессора не определены в том же смысле, в каком символу дается значение, когда, например, вы определяете функцию.
Это может помочь думать о препроцессоре как о механизме замены текста. Когда символ определен, он рассматривается как текстовый текст с прямой заменой до конца файла или до тех пор, пока он не будет определен. Его значение нигде не хранится и, следовательно, не может быть скопировано. Поэтому единственный способ восстановить определение T
после того, как вы #undef
Это должно полностью воспроизвести его значение в новом #define
позже в вашем коде.
Лучшее, что вы можете сделать, это просто не использовать Boost или ходатайствовать, чтобы разработчики JUCE не использовали T
как макрос. (Или, в худшем случае, исправьте это самостоятельно, изменив имя макроса.)