在编写平台相关代码时使用constexpr if而不是宏?

时间:2017-03-04 14:11:35

标签: c++ c++17

既然if constexpr是C ++ 17的一部分,那么在编写平台相关代码和类似代码时,它是否可以替代宏?

我很想知道,因为我真的不喜欢宏,并且只想将它们用于包含守卫和包含。

// those variables should be given by the compiler
constexpr unsigned int __os = 0x1; // current os
constexpr unsigned int __os_win = 0x1; // Windows
constexpr unsigned int __os_linux = 0x2; // Linux-flavors
constexpr unsigned int __os_apple = 0x4; // Mac os

void print_os() {
    if constexpr (__os == __os_win)
        std::cout << "You're on Windows!\n";
    else if constexpr (__os == __os_linux)
        std::cout << "You're on a Linux OS!\n";
    else if constexpr (__os == __os_apple)
        std::cout << "You're on Mac OS!\n";
}

而不是当前的解决方案:

void print_os() {
#ifdef _WIN32
    std::cout << "You're on Windows!\n";
#elif __linux__
    std::cout << "You're on a Linux OS!\n";
#elif __APPLE__
    std::cout << "You're on Mac OS!\n";
}

两种方式在编译时都不会为其他平台生成代码,因此它们在技术上是相同的,因此,我更倾向于constexpr方式(如果可能的话)。

这对于编译器实现上面的constexpr变量是否可行?我找不到gcc和clang的任何功能请求和实现,所以必须有一个原因,他们不想实现第一种方式。为什么会这样?

3 个答案:

答案 0 :(得分:3)

发布此问题一年后,我现在知道为什么这不是一个好主意。这是因为两者实际上并不等效。

if constexpr只是不实例化丢弃分支的工具。而已。这意味着代码如下:

void draw() {
#if LINUX
    ncursesDrawWhatever();
#elif WINDOWS
    Win32Draw();
#endif
}

(现在很好)不等于:

void draw() {
    if constexpr (__linux)
        ncursesDrawWhatever();
    else if constexpr (__win)
        Win32Draw();
}

因为在两个平台上这两个功能都必须可用(而在预处理器版本上则不可用)。在这种情况下,constexpr是完全多余的,因为它什么也不做。不得不在两个平台上都只为一个未被使用的函数定义两个函数有点麻烦,这就是为什么首先以这种方式使用预处理器的原因!

答案 1 :(得分:1)

可能是因为你还没写过。这些都是语言中相当新的东西。像这样的想法需要时间来过滤到实现的实际代码以及事情的完成方式。

作为一个例子,我浏览了Python asyncio包,尽管在该语言中创建了asyncawait个关键字,专门用于支持此包的用例,它在极少数地方使用它们,并且大多数地方仍使用@coroutine装饰器。这并不太令人惊讶。

所以,发布功能请求。请求一些可用于constexpr条件的好的os测试常量。或者甚至可能承诺深入到图书馆来自己实施它们。该功能不到2年。所以,这还没有完成,这还不足为奇。

答案 2 :(得分:-2)

我同意,使用C语法而不是ifdefs更具可读性。为了向后兼容,您可以使用编译标志或编译指示禁止const条件的警告。作为一个关键词,Constexpr可能没有比对相同效果的评论更有用了。