【问题标题】:A name for describing `consteval` function argument being known at compile time but not constexpr用于描述在编译时已知但不为 constexpr 的 `consteval` 函数参数的名称
【发布时间】:2020-08-29 19:02:00
【问题描述】:

consteval 函数的参数是:

  • 某种 在编译时已知
  • 不是 constexpr

Andrew Sutton 在他的论文 Translation and evaluation: A mental model for compile-time metaprogramming 中解释了这种行为背后的动机,this SO post 指出了这一点。


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

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

constexpr int i = foo(9);

但你不能在 consteval 函数本身中将它用作 constexpr

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

上面无法编译,因为 n 不是不是 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);

这是一个术语问题:

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

【问题讨论】:

  • 我会选择constinit。对于这种特殊情况,它可能不是官方术语,但从语义上讲,它几乎可以检查出来。

标签: terminology c++20 consteval


【解决方案1】:

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

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

可以在常量表达式上下文中调用 constexpr 函数(使用 constexprconsteval 声明的函数)。常量表达式上下文是语言要求将表达式作为常量表达式的地方。模板参数、constexpr/constinit 变量的初始化器等等都是常量表达式上下文。

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

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

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

参数本身对于C++来说并不是特殊的。特殊的是函数的定义是什么(即:你的函数是valid in accord with constexpr rules,这个评估是否执行non-constexpr things),函数的调用方式(即:你是否在常量表达式上下文中调用它),以及参数被填充(即:参数是常量表达式)。

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

所以这些东西没有名字。

立即函数(使用consteval 声明的函数)只是一个包含一些额外规则的 constexpr 函数。这些规则阻止您使用leaking the address of an immediate function(即:编译器不必为它们生成真正的函数)。标准规定调用即时函数is always a constant expression context(因此必须按照这些规则调用)。

【讨论】:

    猜你喜欢
    • 2021-10-24
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 2013-10-01
    • 2018-08-02
    • 2010-10-30
    相关资源
    最近更新 更多