因此,通常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是rvalues,但我们没有办法(我猜),它们可以被铸造到constexpr(如果我们可以说通常关于铸造到constexpr),所以在我看来它会被执行在运行时中。但是,没有实际的理由在运行时执行它,因为在编译期间x和y都是已知的。
所以我的问题是现实生活中的情况如何?此函数是在运行时还是编译时执行
答案 0 :(得分:2)
根据标准草案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
,则编译将失败。
答案 1 :(得分:2)
constexpr int fun(int x, int y) { return x+y; }
fun(5,6) // << constant expression?
tl; dr
5
和6
是常量表达式。因此fun(5,6)
也是一个常量表达式,将在编译时进行求值,这是必需的(例如非类型模板)。
<强>东西... 强> 我快速浏览了标准,希望我没有错过任何重要的观点。
我们已经从@ 42的答案中得知:
根据N4527 int
是 constexpr函数的有效参数类型,因为它是一个文字类型(因为它是一个标量类型,是§3.9/ 10同一文件的文字类型)。因此,fun
是一个有效的constexpr函数。
它提供的代码将fun(5,6)
置于需要常量表达式的上下文中,并且似乎被某些编译器接受。
现在的问题是这是否是有效的,符合标准的行为。
来自N4527的§5.20说:
条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:
- 这里列出了阻止表达式成为核心常量表达式的大量事项
该列表不包含“具有常量表达式参数的constexpr函数”,因此它们是核心常量表达式(除非它们在使用时未定义)。
因此,如果5
和6
是常量表达式,那么fun(5,6)
是一个常量表达式,如果fun
是有效的 constexpr函数并且在使用之前定义。给定的函数满足§7.1.5/ 3中的要求约束,并且是一个有效的 constexpr函数。
根据§2.13.2
,5
和6
都是类型int
的整数文字
1)整数文字是一个没有句号或指数部分的数字序列,可选的分隔单引号在确定其值时被忽略。 [...]
2)整数文字的类型是表5中相应列表中第一个可以表示其值的列表。
后缀:
none
,十进制文字:int
,long int
,long long int
现在再次看§5.20,我们看到:两者都是常数表达式。