为什么函数可以是 constexpr,即使它们不能在常量表达式中使用?

use*_*r10 2 c++ constexpr c++20

说明constexpr符声明可以在编译时计算函数或变量的值。函数的唯一用例constexpr是它能够在编译时解析。或者更准确地说,是constexpr用变量的结果初始化变量的能力。如果将函数的结果存储到变量constexprconstexpr,它会强制函数成为纯函数(看起来像,不确定)。

add为什么可以标记该功能constexpr

int global = 200;
constexpr int add(int a) {
    global += a; //works perfectly at run-time but no way to run at compile time
    return global;
}

int main() {
    // will not run since it attempts to access run-time storage,
    // global is not const and so on 
    constexpr int a = add(1);
    // works, but only at run-time, yet the function is constexpr
    int b = add(1);           
}
Run Code Online (Sandbox Code Playgroud)

这种功能的用例是什么?为什么它被允许呢?函数constexpr可以使用运行时输入,因为允许在运行时使用。但是,在函数体中允许非常量运行时变量的目的是什么constexpr

有人知道为什么标准允许这样的功能吗?

Jar*_*d42 5

来自C++20 标准,[dcl.constexpr] p6(强调我的)在 C++23 之前,

对于既不是默认值也不是模板的 constexpr 函数 [...],如果不存在参数值,使得函数 [...] 的调用可以是核心常量表达式的计算子表达式,[...] ,程序格式错误,无需诊断

所以不需要诊断。

Clang/gcc 成功诊断问题Demo

在 C++23 中,现在拥有这样的函数是合法的

编写一个 constexpr 函数,其调用永远无法满足核心常量表达式的要求,这是可能的。

基本原理可以在论文Relaxing some constexprcriteria中找到。

粗略地说,它是面向未来的(一般情况):版本 N 中
没有的功能可能会出现在版本 N+1 中。constexprconstexpr