Namespaces
Variants

consteval specifier (since C++20)

From zh.cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous
  • consteval - 指定函数为 立即函数 ,即对该函数的每次调用都必须生成编译时常量

目录

说明

consteval 说明符用于声明函数或函数模板为 立即函数 ,即每个对该函数的 潜在求值 调用必须(直接或间接)产生一个编译期 常量表达式 。

立即函数是一种 constexpr函数 ,根据具体情况需满足其要求。与 constexpr 相同, consteval 说明符隐含 inline 特性。但该说明符不得应用于析构函数、分配函数或释放函数。

声明为 consteval 的函数或函数模板不可同时指定 constexpr ,且该函数或函数模板的所有重声明也必须指定 consteval 。

对立即函数的潜在求值调用,若其最内层非块作用域不是某个立即函数的 函数形参作用域 或 consteval if 语句 的真分支 (C++23 起) ,则必须产生常量表达式;此类调用被称为 立即调用 。

consteval int sqr(int n)
{
    return n*n;
}
constexpr int r = sqr(100); // 正确
int x = 100;
int r2 = sqr(x);            // 错误:调用无法产生常量
consteval int sqrsqr(int n)
{
    return sqr(sqr(n));     // 此处不是常量表达式,但允许
}
constexpr int dblsqr(int n)
{
    return 2 * sqr(n);      // 错误:外围函数不是 consteval
                            // 且 sqr(n) 不是常量
}

一个 标识符表达式 若表示立即函数,则仅可出现在立即调用的子表达式内,或处于 立即函数上下文 中(即上文提及的、调用立即函数无需为常量表达式的语境)。可以获取立即函数的指针或引用,但不得脱离常量表达式求值范围:

consteval int f() { return 42; }
consteval auto g() { return &f; }
consteval int h(int (*p)() = g()) { return p(); }
constexpr int r = h();  // 正确
constexpr auto e = g(); // 非法的:指向立即函数的指针不是常量表达式的合法结果
                        // 

注释

功能测试宏 值 标准 功能特性
__cpp_consteval 201811L (C++20) 即时函数
202211L (C++23)
(DR20)
使 consteval 向上传播

关键词

consteval

示例

#include <iostream>
// 如果输入在编译期已知,此函数可能在编译期求值
// 否则将在运行时执行
constexpr unsigned factorial(unsigned n)
{
    return n < 2 ? 1 : n * factorial(n - 1);
}
// 使用 consteval 强制函数在编译期求值
consteval unsigned combination(unsigned m, unsigned n)
{
    return factorial(n) / factorial(m) / factorial(n - m);
}
static_assert(factorial(6) == 720);
static_assert(combination(4, 8) == 70);
int main(int argc, const char*[])
{
    constexpr unsigned x{factorial(4)};
    std::cout << x << '\n';
    [[maybe_unused]]
    unsigned y = factorial(argc); // 正确
//  unsigned z = combination(argc, 7); // 错误:'argc' 不是常量表达式
}

输出:

24

参见

constexpr 说明符 (C++11) 指定变量或函数的值可在编译时计算
constinit 说明符 (C++20) 断言变量具有静态初始化,即 零初始化 和 常量初始化
常量表达式 定义可在编译时求值的 表达式