C++ 11,如何在 #if 中使用 const

Cyd*_*uzo 6 c++ if-statement constants

我在我的代码中使用了一个 const 变量。并想告诉我的预处理器使用它。即:

const double x = 1.2;
const bool xIsZero = x==0;

#if xIsZero
...
#endif
Run Code Online (Sandbox Code Playgroud)

但这不起作用。在 C++ 17 中,if constexpr没有诀窍。但我现在坚持使用 C++11。

因此,我可以使用以下解决方法:

#define X 1.2
#define xIsZero (x==0)
const double x = X;

#if xIsZero
...
#endif
Run Code Online (Sandbox Code Playgroud)

但我只是不喜欢将 x 赋予 #define,我想直接将其赋予常量。有没有办法做到这一点?

Evg*_*Evg 4

如果在编译时已知条件,则可以使用重载来模拟if constexprC++11:

void foo(std::true_type) {   // if (xIsZero)
}

void foo(std::false_type) {  // if (!xIsZero)
}

constexpr bool xIsZero = ...;
foo(std::integral_constant<bool, xIsZero>{});
Run Code Online (Sandbox Code Playgroud)

正如LoPiTaL在评论中指出的那样,这并不完全等同于if constexpr,因为两者foo都必须编译。当我们使用模板时,这项技术就变得很重要。使用 plain 时,if两个分支都使用同一组模板参数进行编译。通过重载,我们可以有效地丢弃分支。

例如,此代码失败:

template<unsigned int i>
void foo(std::integral_constant<unsigned int, i>) {
    if (i > 0) {
        consume_positive_i(i);
        foo(std::integral_constant<unsigned int, i - 1>{});
    } else
        consume_zero_i(i);
}
Run Code Online (Sandbox Code Playgroud)

在 C++17 中,可以使用以下命令轻松修复if constexpr

template<unsigned int i>
void foo(std::integral_constant<unsigned int, i>) {
    if constexpr (i > 0) {
        consume_positive_i(i);
        foo(std::integral_constant<unsigned int, i - 1>{});
    } else
        consume_zero_i(i);
}
Run Code Online (Sandbox Code Playgroud)

C++11 中的解决方法是重载:

void foo(std::integral_constant<unsigned int, 0>) {   
    consume_zero_i(i);
}

template<unsigned int i>
void foo(std::integral_constant<unsigned int, i>) {
    consume_positive_i(i);
    foo(std::integral_constant<unsigned int, i - 1>{});
}
Run Code Online (Sandbox Code Playgroud)