我可以重新定义C ++宏然后再定义它吗?

时间:2009-11-24 23:56:17

标签: c++ boost macros c-preprocessor

我在我的代码中使用JUCE库和许多Boost标头。 Juce将“T”定义为宏(呻吟),Boost经常在其模板定义中使用“T”。结果是,如果你以某种方式在Boost头之前包含JUCE头,那么预处理器会在Boost代码中扩展JUCE宏,然后编译器就会无可救药地丢失。

在大多数情况下保持我的包含顺序并不难,但是如果你有一个包含其他类的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 个答案:

答案 0 :(得分:61)

正如greyfade指出的那样,你的___T___技巧不起作用,因为预处理器是一个非常简单的生物。另一种方法是使用pragma指令:

 // juice includes here
 #pragma push_macro("T")
 #undef T
 // include boost headers here
 #pragma pop_macro("T")

这应该适用于MSVC ++,GCC已添加对pop_macropush_macro的支持,以便与之兼容。从技术上讲,它依赖于实现,但我认为没有一种标准的方法可以暂时抑制定义。

答案 1 :(得分:11)

你可以将违规库包装在另一个包含中并将#define T陷入其中吗?

例如:

JUICE_wrapper.h:     
#include "juice.h"
#undef T

main.cpp:    
#include "JUICE_wrapper.h"    
#include "boost.h"

 rest of code....

答案 2 :(得分:4)

  

然后我想也许我可以像这样做一些循环的#define技巧:

C预处理器不能以这种方式工作。预处理器符号的定义与给定符号的意义不同,意味着在例如时定义一个函数。

将预处理器视为文本替换引擎可能会有所帮助。定义符号时,它将被视为直接文本替换,直到文件结尾或未定义。它的值不会存储在任何地方,因此无法复制。因此,在您T之后恢复#undef定义的唯一方法是在代码中的新#define中完全重现其值。

您可以做的最好的事情就是不要使用Boost或请求JUCE的开发人员不要将T用作宏。 (或者,最糟糕的情况是,通过更改宏的名称来自行修复。)