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

时间:2018-09-20 22:03:13

标签: c++ const c++17 constexpr

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

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

已编辑以添加代码示例。

所以在标题中我想要类似

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子句被丢弃/不编译)以及C和D行(以及所有执行相同操作的操作) ,或依赖于BuildPlatform的运行时存储)生成编译器错误。

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

3 个答案:

答案 0 :(得分:1)

部分可行:

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
    }
}

答案 1 :(得分:0)

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

对于浮点值,没有任何constexpr方法可以保证不使用ODR。使用ODR往往会导致为该常数创建存储。

您可以使用constexpr函数来返回浮点值,但是该函数可以轻松地进行存储。

答案 2 :(得分:0)

也许您可以使用它。

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)
{   
}