使用constexpr代替#define和#ifdef进行条件编译

Using constexpr to replace #define and #ifdef for conditional compilation

我正在尝试用 constexpr 变量和 ifs 替换我用来控制条件编译的预处理器 #define 和 #if/#ifdef。

是否可以声明 constexpr 变量,使它们重现 #defines,因为它们不分配运行时存储,并且取一个地址会导致编译时错误?

编辑以添加代码示例。

所以在 headers 我想有类似

的东西
namespace ExampleNamespace
{
  enum class Platform : int {Darwin, Linux, Windows};

  constexpr Platform BuildPlatform = Platform::Darwin;  // Line A.
};

在我想要的代码中

if constexpr (Platform::Darwin == BuildPlatform)        // Line B.
  {
    cout << "Platform is Darwin" << endl;
  }
else
  {
    cout << "Platform is not Darwin" << endl;
  };

const Platform *const PlatformAddress = &BuildPlatform; // Line C.
const Platform &BuildPlatform2 = BuildPlatform;         // Line D.

然后的目标是更改 A 行上 BuildPlatform 的定义,以便在编译时评估 B 行(并且 else 子句得到 discarded/not 编译)和 C 行和 D 行(以及任何做同样的事情,或者依赖于 BuildPlatform 的运行时存储)生成编译器错误。

这样的构造在 C++17 中可行吗?

部分可能:

if constexpr (Platform::Darwin == BuildPlatform) {        // Line B.
    std::cout << "Platform is Darwin" << std::endl;
} else {
    std::cout << "Platform is not Darwin" << std::endl;
}

但由于 template <typename T> void foo() {static_assert(false);} 格式错误, 所有分支的代码都应该具有某种有效性。

#ifdef (DarwinPlatform) // constexpr cannot be used here, you have to 
                        //rely on MACRO here
# include <darwin.h>     // Some OS specific header
#endif

void foo()
{
    if constexpr (Platform::Darwin == BuildPlatform) {
        DarwinMethod(); // Won't compile on other platforms as
                        // the method doesn't exist.
        // you should make the block template with template dependent code
        // to allow code to compile.
        // as http://coliru.stacked-crooked.com/a/c695575e4dcdecee
    }
}

对于标志和整数,枚举值有效。

对于浮点值,没有保证不使用 ODR 的 constexpr 方法。 ODR 使用往往会导致为常量创建存储。

您可以使用一个 returns 浮点值的 constexpr 函数,但该函数很容易占用存储空间。

也许你可以用这个。

enum class Platform { Darwin, Linux, Windows };

#ifdef __darwin__
constexpr Platform  BuildPlatform = Platform::Darwin;
#elif __linux__
constexpr Platform  BuildPlatform = Platform::Linux;
#elif __WIN32
constexpr Platform  BuildPlatform = Platform::Windows;
#endif

// your code then uses it like this

if constexpr (BuildPlatform == Platform::Darwin) 
{         
}
else if constexpr (BuildPlatform == Platform::Linux)
{
}
else if constexpr (BuildPlatform == Platform::Windows)
{   
}