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

Using constexpr if instead of macros when writing platform dependent code?

现在 if constexpr 是 C++17 的一部分,在编写平台相关代码和类似代码时它是否是宏的良好替代品?

我想知道,因为我真的不喜欢宏,并且只想将它们用于 include guards 和 includes。

// 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 的任何功能请求和实现,所以他们不想实现第一种方式一定是有原因的。为什么会这样?

我同意,使用 C 语法而不是 ifdefs 更具可读性。为了向后兼容,您可以使用编译标志或 pragma 来抑制 const 条件的警告。 Constexpr 作为关键字可以说并不比具有相同效果的注释更有用。

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

例如,我浏览了 Python asyncio 包,尽管在语言中创建了 asyncawait 关键字专门支持使用- 这个包的案例,它在很少的地方使用它们并且仍然使用 @coroutine 装饰器 most 地方。这并不奇怪。

因此,post 功能请求。要求一些可以与 constexpr 条件一起使用的不错的 os 测试常量。或者甚至可能致力于深入研究库以自己实现它们。该功能还不到 2 年。所以这还没有完成也就不足为奇了。

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

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

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

(现在完全没问题)不等同于:

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

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