1

函数的参数consteval是:

  • 在编译时就知道
  • 不是 constexpr

Andrew Sutton 在他的论文翻译和评估:编译时元编程的心理模型中解释了这种行为背后的动机,正如这篇 SO 帖子所指出的那样。


您可以从consteval函数返回参数并将其用作constexpr

consteval int foo(int n) {
    return n;
}

constexpr int i = foo(9);

但是你不能constexpr在函数内部使用它consteval

// fails to compile
consteval int abs(int n) {
    if constexpr (n < 0) {
        return -n;
    }
    else {
        return n;
    }
}

上面无法编译,因为n不是a 。constexpr

您当然可以使用一个简单的 if,它将在编译时进行评估:

// compiles
consteval int abs(int n) {
    if (n < 0) {
        return -n;
    }
    else {
        return n;
    }
}

constexpr int i = -9;
constexpr int num = abs(i);

这是一个术语问题:

是否有一个在编译时已知不是常量表达式的常用名称?

4

1 回答 1

2

TL;DR:不,C++ 标准中没有这样的术语。

就标准而言,“在编译时已知”不是一回事。有“常量表达式”的概念,也有“常量求值”的概念。

可以在常量表达式上下文中调用constexpr 函数(用constexpror声明的函数)。consteval常量表达式上下文是语言要求表达式是常量表达式的地方。模板参数、constexpr/constinit变量的初始值设定项等等都是常量表达式上下文。

在常量表达式上下文中调用 constexpr 函数时,它们会生成常量表达式……或者您没有正确构造函数/参数并出现编译错误。就标准而言,差不多就是这样。

哦,是的,有关于 constexpr 函数的规则。他们被禁止执行某些 C++ 操作。并且有一些关于从常量表达式上下文调用它们的规则。但除此之外,就是这样。

您所指的区别仅仅是 constexpr 函数中允许的内容的产物。您可以返回 constexpr 函数的参数,因为 constexpr 函数的返回值在语法上不是常量表达式。在适当的情况下,该功能可以进行持续评估,但这就是该主题需要说明的所有标准。

参数本身对 C++ 来说并不特殊。特殊的是函数的定义是什么(即:您的函数是否符合 constexpr 规则有效,并且此评估是否执行非 constexpr 的事情),函数的调用方式(即:您是否在常量表达式上下文中调用它) ,以及如何填写参数(即:参数是否为常量表达式)。

按照标准,有表达式是常量表达式,也有表达式不是。但是,其值是通过常量表达式求值生成但本身不是语言常量表达式的表达式并不是标准需要定义的概念。它们只是价值观;它们是否在常量表达式评估中与程序的行为并不真正相关。

所以这些东西没有名字。

立即函数(用 声明的函数consteval)只是一个 constexpr 函数,其中包含一些额外的规则。这些规则可以防止您泄露立即函数的地址(即:编译器不必为它们生成真正的函数)。并且标准说调用立即函数始终一个常量表达式上下文(因此必须根据这些规则调用)。

于 2020-05-13T15:28:11.707 回答