constexpr 函数和硬编码参数

constexpr function and hardcoded arguments

本文关键字:编码 参数 函数 constexpr      更新时间:2023-10-16

所以通常constexpr函数是在编译时执行的函数,当传递给它的参数也是constexpr

时,如下所示:
constexpr int function(int x, int y){
   return x+y;
}

参数声明如下:

constexpr int x = 5;
constexpr int y = 6;

将在编译时执行,但具有以下参数声明:

int x=5;
int y=6;

不会的。我想知道如果我们通过以下方式调用这个函数会发生什么:

function(5,6);

从技术角度来看,5 和 6 是右值,但没有办法(我猜(它们可以转换为 constexpr(如果我们可以笼统地说到 constexpr(,所以在我看来它将在运行时执行。但是,没有实际的理由在运行时执行它,因为在编译期间 x 和 y 都是已知的。

所以我的问题是它在现实生活中怎么样?此函数是在运行时还是编译时执行

constexpr int fun(int x, int y) { return x+y; }
fun(5,6) // << constant expression?

博士

56是常量表达式。因此,fun(5,6)也是一个常量表达式,并将在编译时进行计算,这是必需的(例如非类型模板(。

东西。。。我快速浏览了标准,我希望我没有错过任何重要点。

我们已经从@42的回答中知道:

  • 根据 N4527,intconstexpr 函数的有效参数类型,因为它是文本类型(因为它是标量类型,根据同一文档的 §3.9/10 是文本类型(。因此,fun 是一个有效的 constexpr 函数。

  • 它提供了将fun(5,6)放入需要常量表达式并且似乎被某些编译器接受的上下文中的代码。

现在的问题是,这是否是有效的、符合标准的行为。

§5.20 从 N4527 说:

条件表达式 e 是核心常量表达式,除非按照抽象机器 (1.9( 的规则对 e 进行计算,否则将计算以下表达式之一:

  • 这里有一大堆阻止表达式成为核心常量表达式的东西

该列表不包含"带有常量表达式参数的constexpr函数",因此它们是核心常量表达式(除非它们在使用时未定义(。

因此,如果 56 是常量表达式,那么如果 fun 是一个有效的 constexpr 函数并且在使用它之前被定义,则fun(5,6)是一个常量表达式。给定的函数满足 §7.1.5/3 中的必要约束,并且是一个有效的 constexpr 函数

56 都是 §2.13.2 中 int 类型的整数文本

1( 整数文字是没有句点或指数部分的数字序列,可选的分隔单引号在确定其值时被忽略。[...]

2( 整数文本的类型是表 5 中相应列表中的第一个,可以在其中表示其值。

后缀:none,十进制文字:intlong intlong long int

现在再看§5.20,我们看到:两者都是常量表达式。

根据草案标准 N4527 7.1.5/3 constexpr 说明符 [dcl.constexpr](强调我的(:

constexpr 函数的定义应满足以下条件 约束:

(3.1( — 它不应是虚拟的 (10.3(;

(3.2( — 其返回类型应为文字类型;

(3.3( — 其每个参数类型应为文字类型;

因此,调用function(5,6);满足constexpr函数的定义,并在编译时执行。

此外,您可以使用 std::integral_constant 自行测试:

#include <iostream>
#include <type_traits>
constexpr int fun(int x, int y) {
   return x + y;
}
int main() {
    std::cout << std::integral_constant<int, fun(5, 6)>::value << std::endl;
}

现场演示

如果fun中的输入参数未constexpr则编译将失败。