除了使用 #define 进行条件编译之外,还有其他选择吗?
Are there any options other than using #define for conditional compilation?
我想使用条件编译来测试代码的不同属性;但是,我不想污染全局命名空间。有人会好心让我知道是否有办法在不使用#define
的情况下使用条件编译吗?
我已经搜索了一个选项,但大多数其他帖子都提到了static const
等在运行时选择不同代码的使用。但是,我想编译不同的代码。例如,代替:
#define A_HASH_DEFINE
...
#ifdef A_HASH_DEFINE
Some code
#elif ANOTHER_HASH_DEFINE
Some other code
#endif
我希望能够使用带有范围的东西,例如:
scope::A_SCOPED_HASH_DEFINE
...
#ifdef scope::A_SCOPED_HASH_DEFINE
Some code
#elif scope::ANOTHER_SCOPED_HASH_DEFINE
Some other code
#endif
如果您使用的是 C++17,则应使用if constexpr
.
它本质上是一个if
语句,其中分支是在编译时选择的,任何未采用的分支都会被丢弃。它比在整个代码中散布#ifdef
更干净。
#ifdef _DEBUG
constexpr bool debug_mode = true;
#else
constexpr bool debug_mode = false;
#endif
if constexpr (debug_mode) {
//debug code
}
您可以在FooNathan的博客中阅读有关它如何替换#if … #else
的更多信息:
今年是 2017 年 - C++ 中还需要预处理器吗?
使用预处理器定义时,我们始终必须处理污染"全局命名空间"的权衡。
当然,它不是真正的全局命名空间,但它是自己的命名空间:问题是,由于它们的性质,这些宏名称实际上在每个作用域中都有效。
我们只是接受这一点。
我们试图通过将它们保留在单独的翻译单元来限制它们。或者,如果它们需要在标头中,我们切换到const bool
s。
如果您需要真正意义上的条件编译,并且您可以使用if constexpr
在非预处理器C++中拼写它,那就更好了。
否则,这只是我们必须处理的事情。我们至少尝试使用描述性名称,并避免使用可能与第三方标头冲突的常用术语。如果他们这样做,我们会改变他们。
如果您仍然发现宏污染太大,则可能是您的切换逻辑封装了太多代码。在这种情况下,您可以考虑将逻辑移动到构建系统中,并首先更改构建的源文件。
例如,OpenGL 渲染器实现与 DirectX 渲染器实现(该示例仅在构建时在它们之间切换时才有效,就像使用宏一样!
在处理条件编译时,省略在编译时声明定义是很常见的,使其更加类型安全的一个很好的技巧是使用枚举(布尔值也可以工作)来确保在编译时定义有效的值。
例
enum class SystemEnum { MAC, LINUX, WINDOWS };
const SystemEnum mySystem = SystemEnum::MY_SYSTEM;
void func() {
#if MY_SYSTEM == MAC
doMacStuff();
#elif MY_SYSTEM == LINUX
doLinuxStuff();
#elif MY_SYSTEM == WINDOWS
doWindowsStuff();
#else
#error "You must define MY_SYSTEM to compile this"
#endif
if constexpr (mySystem == SystemEnum::MAC)
doMacStuff();
else if constexpr (mySystem == SystemEnum::LINUX)
doLinuxStuff();
else if constexpr (mySystem == SystemEnum::WINDOWS)
doWindowsStuff();
else
doError();
}
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- 如何使用默认参数等选择模板专业化
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 为什么这个选择排序算法仍然切换一个元素,当它已经是其他元素中最小的元素时?
- cv::cuda::setTo()是否有其他选择
- 有没有其他选择可以打破?
- 除了使用 #define 进行条件编译之外,还有其他选择吗?
- 谷神星求解器:残差函子使用的可变对象是否良好实践?还有什么其他选择
- 在C 中,Haskell下划线有其他选择吗?
- 有没有机会触发一个不知道拥有队列的kevent?还有其他选择吗?
- 除了使用OpenCV的imdecode之外,还有其他选择吗?太慢了
- C++ 如何通过可选的typedef,使用SFINAE或其他方式选择类
- 从一个组合框中选择项目,然后从其他组合框中删除该项目
- 如何存储需要随机选择和删除的数据,矢量,哈希表或其他
- 除了制作类的const版本,还有其他选择吗
- 为什么glReadPixels这么慢,有没有其他选择?
- 除了这一长串"if argA == argB do ..."之外,还有其他选择吗?
- 从下拉框中选择其他项目时更改选项卡小部件的 currentIndex()
- Objective-c选择器,其他语言如c++, python, ruby, java, javascript有类似的东
- 是否有可能在C中使用系统api启动一个kill命令?如果没有其他选择的话