用于描述在编译时已知但不是 constexpr 的“consteval”函数参数的名称
A name for describing `consteval` function argument being known at compile time but not constexpr
consteval
函数的参数是:
- 编译时已知
- 但是不是constexpr
Andrew Sutton 在他的论文 Translation and evaluation: A mental model for compile-time metaprogramming, as pointed by this SO post 中解释了这种行为背后的动机。
您可以 return 来自 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);
这是一个术语问题:
是否有一个在编译时已知但不是常量表达式的常用名称?
TL;DR:不,C++ 标准中没有这样的术语。
就标准而言,"known at compile time"不是东西。有一个"constant expression"的概念,有一个"constant evaluation"的概念。
constexpr 函数(用 constexpr
或 consteval
声明的函数)可以在常量表达式上下文中调用。常量表达式上下文是语言 要求 表达式成为常量表达式的地方。 constexpr/constinit
变量的模板参数、初始值设定项等都是常量表达式上下文。
当在常量表达式上下文中调用 constexpr 函数时,它们会生成常量表达式...或者您没有正确构造 function/arguments 并得到编译错误。就标准而言,差不多就是这样。
哦,是的,有关于 constexpr 函数的规则。他们被禁止执行某些 C++ 操作。并且有关于从常量表达式上下文调用它们的规则。但除此之外,仅此而已。
您所指的区别仅仅是 constexpr 函数中允许的结果的产物。您可以 return constexpr 函数的参数,因为 constexpr 函数的 return 值在语法上不是常量表达式。在适当的情况下,该功能可以进行不断的评估,但这就是关于该主题的所有标准需要说明的内容。
参数本身不是C++特有的。特别之处在于函数的定义是什么(即:是你的函数valid in accord with constexpr rules, and does this evaluation do non-constexpr things),函数是如何被调用的(即:你是在常量表达式上下文中调用它),以及参数是如何填充的(即:参数是常量表达式)。
按照标准,有表达式是常量表达式,也有表达式不是。但是,其值通过常量表达式求值生成但本身不是语言常量表达式的表达式并不是标准 需要 定义的概念。它们只是价值观;它们是否在常量表达式求值中与程序的行为并不真正相关。
所以这些东西没有名字。
立即函数(用 consteval
声明的函数)只是一个包含一些额外规则的 constexpr 函数。这些规则阻止您 leaking the address of an immediate function (ie: compilers don't have to generate real functions for them). And the standard says that invoking an immediate function is always a constant expression context(因此必须根据这些规则调用)。
consteval
函数的参数是:
- 编译时已知
- 但是不是constexpr
Andrew Sutton 在他的论文 Translation and evaluation: A mental model for compile-time metaprogramming, as pointed by this SO post 中解释了这种行为背后的动机。
您可以 return 来自 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);
这是一个术语问题:
是否有一个在编译时已知但不是常量表达式的常用名称?
TL;DR:不,C++ 标准中没有这样的术语。
就标准而言,"known at compile time"不是东西。有一个"constant expression"的概念,有一个"constant evaluation"的概念。
constexpr 函数(用 constexpr
或 consteval
声明的函数)可以在常量表达式上下文中调用。常量表达式上下文是语言 要求 表达式成为常量表达式的地方。 constexpr/constinit
变量的模板参数、初始值设定项等都是常量表达式上下文。
当在常量表达式上下文中调用 constexpr 函数时,它们会生成常量表达式...或者您没有正确构造 function/arguments 并得到编译错误。就标准而言,差不多就是这样。
哦,是的,有关于 constexpr 函数的规则。他们被禁止执行某些 C++ 操作。并且有关于从常量表达式上下文调用它们的规则。但除此之外,仅此而已。
您所指的区别仅仅是 constexpr 函数中允许的结果的产物。您可以 return constexpr 函数的参数,因为 constexpr 函数的 return 值在语法上不是常量表达式。在适当的情况下,该功能可以进行不断的评估,但这就是关于该主题的所有标准需要说明的内容。
参数本身不是C++特有的。特别之处在于函数的定义是什么(即:是你的函数valid in accord with constexpr rules, and does this evaluation do non-constexpr things),函数是如何被调用的(即:你是在常量表达式上下文中调用它),以及参数是如何填充的(即:参数是常量表达式)。
按照标准,有表达式是常量表达式,也有表达式不是。但是,其值通过常量表达式求值生成但本身不是语言常量表达式的表达式并不是标准 需要 定义的概念。它们只是价值观;它们是否在常量表达式求值中与程序的行为并不真正相关。
所以这些东西没有名字。
立即函数(用 consteval
声明的函数)只是一个包含一些额外规则的 constexpr 函数。这些规则阻止您 leaking the address of an immediate function (ie: compilers don't have to generate real functions for them). And the standard says that invoking an immediate function is always a constant expression context(因此必须根据这些规则调用)。