返回语句中的C ++ constexpr函数 [英] C++ constexpr function in return statement
问题描述
为什么在编译时不对constexpr函数进行求值,而在运行时在主函数的return语句中求值?
Why is a constexpr function no evaluated at compile time but in runtime in the return statement of main function?
它尝试了
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
const int x = fac<3>();
return x;
}
,结果为
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 6
mov eax, 6
pop rbp
ret
使用gcc 8.2。但是当我在return语句中调用函数
with gcc 8.2. But when I call the function in the return statement
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
return fac<3>();
}
我得到
int fac<1>():
push rbp
mov rbp, rsp
mov eax, 1
pop rbp
ret
main:
push rbp
mov rbp, rsp
call int fac<3>()
nop
pop rbp
ret
int fac<2>():
push rbp
mov rbp, rsp
call int fac<1>()
add eax, eax
pop rbp
ret
int fac<3>():
push rbp
mov rbp, rsp
call int fac<2>()
mov edx, eax
mov eax, edx
add eax, eax
add eax, edx
pop rbp
ret
为什么在编译时评估第一个代码,而在运行时评估第二个代码?
Why is the first code evaluated at compile time and the second at runtime?
我也尝试过这两个片段都使用clang 7.0.0,并且在运行时进行评估。为什么这对clang无效?
Also I tried both snippets with clang 7.0.0 and they are evaluated at runtime. Why is this not valid constexpr for clang?
所有评估都是在Godbolt编译器资源管理器中完成的。
All evaluation was done in godbolt compiler explorer.
推荐答案
关于 constexpr
的一个常见误解是,它表示这将在编译时进行评估 1 。
A common misconception with regard to constexpr
is that it means "this will be evaluated at compile time"1.
不是。引入了 constexpr
是为了让我们编写自然的代码,这些代码可能在需要它们的上下文中生成 常量表达式。这意味着这必须在编译时可以评估 ,这是编译器将检查的内容。
It is not. constexpr
was introduced to let us write natural code that may produce constant expressions in contexts that need them. It means "this must be evaluatable at compile time", which is what the compiler will check.
因此,如果您编写了 constexpr
函数返回一个int,您可以使用它来计算模板参数, constexpr
变量的初始化程序(也 const
(如果是整数类型)或数组大小。您可以使用该函数来获取自然的,说明性的,可读的代码,而不用过去使用过的旧的元编程技巧。
So if you wrote a constexpr
function returning an int, you can use it to calculate a template argument, an initializer for a constexpr
variable (also const
if it's an integral type) or an array size. You can use the function to obtain natural, declarative, readable code instead of the old meta-programming tricks one needed to resort to in the past.
但是 constexpr
函数仍然是常规函数。 constexpr
说明符并不意味着编译器拥有 2 可以对其进行优化以使其在编译时进行折叠并不断折叠。
But a constexpr
function is still a regular function. The constexpr
specifier doesn't mean a compiler has2 to optimize it to heck and do constant folding at compile time. It's best not to confuse it for such a hint.
1 > sup>-感谢 user463035818 的措词。
2 -c + +20 和 consteval
是一个不同的故事:)
1 - Thanks user463035818 for the phrasing.
2 - c++20 and consteval
is a different story however :)
这篇关于返回语句中的C ++ constexpr函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!