2010-11-08 83 views
11

可能重复:
Can I redefine a C++ macro then define it back?保留预处理器定义

说我有一个使用该名称BLAH一个变量一些代码。假设BLAH是许多标准头文件(定义为10)中常见的预处理器定义,所以如果我的文件被其中任何一个文件包含后,代码就会中断,因为BLAH被转换为10;因此,我必须#undef BLAH。但其他标题也可能取决于BLAH,因此我必须在完成标题后将BLAH恢复为原始值。是否可以这样做:

#ifdef BLAH 
#define BLAH_OLD BLAH 
#undef BLAH 
#endif 

... code ... 

// restore BLAH to 10 
#ifdef BLAH_OLD 
#define BLAH BLAH_OLD 
#end 

?这不,当然工作,因为BLAH没有扩大到10我曾尝试做一些像

#define EXPAND_AGAIN(x) x 
#define EXPAND(x) EXPAND_AGAIN(x) 
#define BLAH_OLD EXPAND(BLAH) 

但这也不管用,因为Expand是从字面上,而不是扩大。我正在使用MSVC 2008/2010,但如果该解决方案也适用于大多数其他编译器,那将是可爱的。

+3

您是否考虑过更改变量命名? – 2010-11-08 21:18:31

+0

更改变量的名称;如果这是一个问题,那么你在那里会遇到可怕的惯例。而如何而不是“让我们说”你说“这是我试图解决的实际问题。” – GManNickG 2010-11-08 21:34:50

+1

你确实认识到,从几乎一开始,这是一个约定,全部大写的标识符都被保留给预处理器使用(为了避免这样的事情)。 – 2010-11-08 21:49:36

回答

-3

对我来说一个窍门就是在课堂上使用枚举。

class foo 
{ 
public: 
    enum { blah = 10 } myenum; 
} 

然后,你可以使用

foo:blah 

,当你需要 '10'。

因为它是班级的一部分,所以'blah'的其他用途不会发生冲突,您可以保存所有def'ing和undef'ing。

+1

什么? '#define blah 0',破坏你的代码。 – GManNickG 2010-11-08 21:38:01

+0

-1对于通常不起作用的建议。如果“blah”已经被定义为预处理器宏,则枚举定义很可能在语法上是格式不正确的。传递的唯一可能性是“blah”被定义为一个有效的标识符。干杯, – 2010-11-08 21:39:45

+0

用枚举代替宏,处理宏碰撞的所有问题都会消失。它不会修复'推动'一个价值。 – Jay 2010-11-09 14:52:51

0

我曾经相信你尝试过的同样的技巧确实有效,就像我以前自己使用它一样。但我最终了解到,它实际上根本不起作用。简单的答案是NO,你不能保存一个定义的当前值,改变它,然后恢复旧的值。预处理器根本无法这样工作。一旦你定义了一个新的值,旧值就消失了。

19

是的,因为你的编译器支持PUSH/POP宏指令(VISUAL C++,GCC,LLVM都这样做):

#define BLAH 10 

#pragma push_macro("BLAH") 
#undef BLAH 

#define BLAH 5 

... 

#pragma pop_macro("BLAH") 
+0

这似乎是Microsoft特定的编译器。 – 2010-11-08 21:45:19

+0

对不起,标准C++没有定义'push_macro'(Visual C++有这个#pragma,但它不是标准的C++)。干杯, – 2010-11-08 21:47:00

+0

至少有一些GCC版本也支持它。 – 2010-11-08 21:47:07

4

不幸的是,预处理器不支持的定义堆栈。

Boost预处理器库使得预处理器做的事情你永远无法想象它可以做什么(如C++ 98中的有效可变宏),但受到预处理器的固有限制 - 所以,不能做,对不起。

唯一已知的中途补救措施是为宏保留ALL_UPPERCASE_IDENTIFIERS,并始终始终将它们用于宏。它有点减少了名称冲突问题。不幸的是,C标准库定义了一些小写的宏,或者允许它们的存在,例如, assert,但他们只是少数。

从实际的角度来看,主要的问题是Windows编程,其中微软的[windows。h]头文件定义了非大写宏,包括minmax,它们与C++标准库冲突时,包含非大写宏的zillions

因此,对于Windows C++编程,在包含[windows.h]之前总是定义NOMINMAX

Cheers & hth。,

+0

感谢'NOMINMAX',但有'#pragma push_macro'至少 – Sergei 2017-01-27 21:22:18

+0

@Sergei:是的,'#pragma push_macro'是[重复问题中接受的解决方案](http://stackoverflow.com/a/1794089/464581)。但正如我在对这个问题的另一个答案的评论中指出的那样,它在2010年是非标准的。我相信它仍然是非标准的,尽管它至少得到了Visual C++,g ++和clang的支持。 – 2017-01-27 23:59:10