constexpr 函数在编译时不计算值

constexpr function not calculate value in compile time

本文关键字:计算 编译 函数 constexpr      更新时间:2023-10-16

我想比较元编程和 contexpr 在 c++0x 中的使用。然后我在两个模型中都写了一个 fib 函数。当我使用元编程模型时,答案打印出来非常快,因为它是在编译时计算的。但是当我使用 constexpr 函数时,它会在运行时而不是编译时计算值。我使用 g++( gcc ) 4.8 .有人可以帮助我吗?

#include <iostream>
using namespace std;
#define NUM 42
template <unsigned int N>
struct Fibonacci {
    enum { value = Fibonacci<N - 1>::value + Fibonacci<N - 2>::value };
};
template <>
struct Fibonacci<1> {
    enum { value = 1 };
};
template <>
struct Fibonacci<0> {
    enum { value = 1 };
};
constexpr unsigned int fib(unsigned int n)
{
    return (n > 1 ? fib(n-1) + fib(n-2) : 1 );
}
int main()
{
    cout << "Meta_fib(NUM)      : " << Fibonacci<NUM>::value << endl; // compile time :)
    cout << "Constexpr_fib(NUM) : " << fib(NUM) << endl;        // run time :-?
    return 0;
}
我相信

原因是constexpr不能保证在编译时执行。若要强制实施编译时计算,必须将其分配给编译时别名。喜欢

enum {i = fib(NUM)};

至少使用 gcc,您可以通过使其成为静态变量来获取要在编译时计算的 constexpr 值:

static const unsigned fibNUM = fib(NUM);

当我阅读标准时,它仍然允许在启动时计算值,但实际上它将在编译时计算。

一个简单的测试是使用std::array来查看您的constexpr是否真的在编译时完成:

#include <array>
std::array<int, Fibonacci<5>::value> arr;
std::array<int, fib(5)> arr2;

海湾合作委员会没有任何抱怨。

请参阅Bjarne Stroustrup的评论:

。根据标准,Contexpr函数可以在 编译器时间或运行时,除非它用作常量表达式, 在这种情况下,必须在编译时对其进行计算。保证 编译时求值,我们必须在常量的地方使用它 表达式是必需的(例如,作为数组绑定或大小写标签)或 使用它来初始化 constexpr。我希望不要自尊 编译器会错过做我的事情的优化机会 最初说:"一个 constexpr 函数在编译时被计算,如果 它所有的论点都是常量表达式。

constexpr

保证在编译时被计算。这意味着,编译器可以选择是在编译时还是在运行时计算。您可以尝试将其分配给编译时常量并像这样检查...

const long i = fib(NUM);// here i should be initialized at the time of 
                        // declaration
cout << "Meta_fib(NUM)      : " << Fibonacci<NUM>::value << endl; 
cout << "Constexpr_fib(NUM) : " << i << endl;