更安全的条件编译?
在 MSVC C++ 程序中,我有一部分代码,我想根据预处理器定义启用或禁用它,
// 1.h
#ifdef MYOPTION
//...
#endif
但我发现当它在多个编译单元中包含的 .h 文件中使用时,这是相当危险的,因为我可以很容易地获得不一致的标头(我不想全局定义 MYOPTION,因为每次更改它都需要完全重新编译):
// 1.cpp
#define MYOPTION
#include "1.h"
// 2.cpp
#include "1.h"
当然,由于包含链式标头,它比这个简化的示例要复杂得多。
有没有办法避免这种不一致,例如,无需太多努力就可以出现编译时错误?
我想过做 #define MYOPTION 0
或 1
,但后来我不得不写一些
#if MYOPTION == 1
//...
#elif !defined(MYOPTION)
#error ...
#endif
看起来太复杂的东西......也许有更好的选择?
In an MSVC C++ program I have a part of code which I want to enable or disable depending on a preprocessor definition
// 1.h
#ifdef MYOPTION
//...
#endif
But I find that it is quite dangerous when it is used in a .h file included in more than one compilation unit, as I can easily get inconsistent headers (I don't want to define MYOPTION globally as it would require a complete recompilation each time I change it):
// 1.cpp
#define MYOPTION
#include "1.h"
// 2.cpp
#include "1.h"
Of course, it is much more complicated than this simplified example due to the chained header inclusion.
Is there a way to avoid such inconsistency, e.g. have a compile-time error without too much effort?
I thought of doing #define MYOPTION 0
or 1
, but then I would have to write something like
#if MYOPTION == 1
//...
#elif !defined(MYOPTION)
#error ...
#endif
which looks too complicated... Maybe there is a better option?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
像这样的事情怎么样:让 1.h 在 obj 中使用不同的选项定义一个虚拟部分。这样,如果 MYOPTION 的使用不一致,链接器将发出警告。
1.h:
使用 a.cpp 中定义但不在 b.cpp 中定义的 MYOPTION 进行编译会产生此链接器警告(使用 VC 2008):
一致的定义根本不会产生链接器警告。
How about something like this: have 1.h define a dummy section in the obj with different options. This way, if MYOPTION is ever used inconsistently, the linker will issue a warning.
1.h:
Compiling with MYOPTION defined in a.cpp but not in b.cpp yields this linker warning (using VC 2008):
A consistent definition yields no linker warnings at all.
我认为您基本上已经自己列出了大多数解决方案。我会使用最后一个解决方案,但形式可能略有不同:
因为 #if MYOPTION == 1 通常会在每个文件中出现多次。更清楚的是,MYOPTION 是该文件的必需条件。
你说它“看起来太复杂”,但恐怕没有比这更“复杂”的解决方案了。
I think you've listed most solution yourself, basically. I would use the last solution, but perhaps in a slightly different form:
Because often this #if MYOPTION == 1 will appear more than once in each file. It's also clearer that MYOPTION is a requisite for that file.
You say it "looks too complicated", but I'm afraid there's probably no solution that's less "complicated" than this.
假设您确实需要使用定义,最好通过编译器命令行定义它们,而不是在源文件中使用
#define
。然后,您的configure
script/makefile/build 过程设置一次定义,并保证它在所有源文件中正确一致。Assuming that you actually need to use the defines, better is to define them via the compiler command line than
#define
in your source files. Then yourconfigure
script/makefile/build process sets the define once and you're guaranteed that it will agree properly across all source files.也许您想要的是创建一个单独的配置。
您可以转到构建->配置管理器并创建新配置(与调试、发布分开)。创建新配置将允许您定义特定于该配置的预处理器符号。
例如,对于标题为“MyOption 1”的新配置,您可以添加预处理器定义
MYOPTION = 1
。同样的情况也适用于 MYOPTION = 2, 3, ...每个配置都必须单独构建。
DEBUG 和 RELEASE 是单独配置的示例; DEBUG 定义
_DEBUG
,RELEASE 定义NDEBUG
Perhaps what you want is to create a separate configuration.
You can go to Build -> Configuration Manager and create a new configuration (separate from DEBUG, RELEASE). Creating a new configuration will allow you to define preprocessor symbols specific to that configuration.
For example, with a new configuration titled "MyOption 1" you could add the preprocessor definition
MYOPTION = 1
. The same thing goes with MYOPTION = 2, 3, ...Each configuration has to be built separately.
DEBUG and RELEASE are examples of separate configurations; DEBUG defines
_DEBUG
and RELEASE definesNDEBUG