Namespaces
Variants

consteval specifier (since C++20)

From 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) 断言变量具有静态初始化,即 零初始化 常量初始化
常量表达式 定义可在编译时求值的 表达式