constexpr if语句

一般情况下,if 语句的条件表达式在运行时求值。

然而,若条件为常量表达式,如下例所示,则情形有所不同:

#include <iostream>

int main()
{
    constexpr double gravity{ 9.8 };

    // 提示:同一类型的低精度浮点字面量可直接进行相等比较
    if (gravity == 9.8)   // 常量表达式,恒为真
        std::cout << "Gravity is normal.\n";   // 将始终执行
    else
        std::cout << "We are not on Earth.\n"; // 永不执行

    return 0;
}

由于 gravity 被声明为 constexpr 并以值 9.8 初始化,条件 gravity == 9.8 必然为真,于是 else 分支永远不会执行。

在运行时对一个 constexpr 条件求值是一种浪费(其结果始终不变),同样,把永远不会执行的代码也编译进可执行文件也是一种浪费。

C++17 的 constexpr if 语句

C++17 引入了 constexpr if 语句,其条件必须是常量表达式,并在编译时求值。

  • constexpr 条件为真,则整个 if-else 结构被替换为 true-statement
  • 若为假,则整个 if-else 结构被替换为 false-statement(若存在),否则替换为空。

使用 constexpr if 时,需在 if 后添加关键字 constexpr

#include <iostream>

int main()
{
    constexpr double gravity{ 9.8 };

    if constexpr (gravity == 9.8)   // 使用 constexpr if
        std::cout << "Gravity is normal.\n";
    else
        std::cout << "We are not on Earth.\n";

    return 0;
}

编译上述代码时,编译器在编译期求值,发现条件恒为真,于是只保留 std::cout << "Gravity is normal.\n"; 这一语句。

换句话说,编译器实际生成的代码等价于:

int main()
{
    constexpr double gravity{ 9.8 };

    std::cout << "Gravity is normal.\n";

    return 0;
}

最佳实践

当条件为常量表达式时,优先使用 constexpr if 而非普通 if

现代编译器与 C++17 中的 constexpr 条件

出于优化目的,现代编译器通常会把带有 constexpr 条件的普通 if 视为 constexpr if 来处理,但并非强制要求。

若编译器遇到带 constexpr 条件的普通 if,可能会发出警告,提示改用 if constexpr,以确保即使关闭优化也能在编译期完成求值。

关注公众号,回复"cpp-tutorial"

可领取价值199元的C++学习资料

公众号二维码

扫描上方二维码或搜索"cpp-tutorial"