返回语句中的C ++ constexpr函数 [英] C++ constexpr function in return statement

查看:76
本文介绍了返回语句中的C ++ constexpr函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么在编译时不对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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆