Могу ли я переопределить макрос 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 как макрос. (Или, в худшем случае, исправьте это самостоятельно, изменив имя макроса.)

Другие вопросы по тегам