第7.6章: consteval

English

概述

consteval 函数必须在编译期求值。 它不能在运行时运行。如果编译器无法在编译期间求值该函数, 程序就无法编译。

这比 constexpr 更严格。实践中, consteval 很少需要,但当你想保证某个函数永远不会 在运行时执行时,它很有用。

1. 基础示例

consteval 函数必须在常量表达式中调用。


#include 

consteval int double_value(int x)
{
    return x * 2;
}

int main()
{
    using namespace ::fast_io::iomnp;

    constexpr int a = double_value(10);  // OK: compile-time
    print("a = ", a, "\n");

    // int b = double_value(10);        // ERROR: cannot call at runtime
}

第二次调用会失败,因为 double_value 不能在运行时运行。

2. 为什么这很少有用

大多数函数并不需要被限制为只能在编译期求值。 需要时 constexpr 已经允许编译期求值, 同时又仍然允许运行时执行。

consteval 只在以下情况有用:

这些情况在普通应用代码中并不常见。

3. 编译期校验

consteval 函数可以强制那些必须在编译期间检查的约束。


#include 

consteval int positive(int x)
{
    if(x <= 0)
        throw "value must be positive";

    return x;
}

int main()
{
    using namespace ::fast_io::iomnp;

    constexpr int a = positive(5);   // OK
    print("a = ", a, "\n");

    // constexpr int b = positive(-3); // compile-time error
}

任何非法输入都会导致编译期失败。

4. 与 constexpr 的区别

constexpr 函数:

consteval 函数:


constexpr int f(int x) { return x + 1; }   // flexible
consteval int g(int x) { return x + 1; }   // strict

g() 只能在常量表达式中使用。

5. 与 if consteval 的配合

if consteval 检测某个 constexpr 函数是否 正在编译期求值。而 consteval 函数总是在编译期求值。


#include 

constexpr int compute(int x)
{
    using namespace ::fast_io::iomnp;

    if consteval
        print("compile-time path\n");
    else
        print("runtime path\n");

    return x * 3;
}

consteval int force_ct(int x)
{
    return compute(x);  // always compile-time
}

force_ct() 保证 compute() 走编译期 分支。

要点