我想比较元编程和c ++ 0x中constexpr的使用。 然后我在两个模型中写了一个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;
}
答案 0 :(得分:9)
我认为原因是constexpr
无法保证在编译时执行。要强制执行编译时评估,必须将其分配给编译时别名。像,
enum {i = fib(NUM)};
答案 1 :(得分:4)
至少使用gcc,你可以通过使它成为一个静态变量来获得在编译时计算的constexpr值:
static const unsigned fibNUM = fib(NUM);
当我阅读标准时,它仍然允许在启动时计算值,但实际上它将在编译时计算。
答案 2 :(得分:1)
查看您的constexpr
是否真的在编译时完成的简单测试是使用std::array
:
#include <array>
std::array<int, Fibonacci<5>::value> arr;
std::array<int, fib(5)> arr2;
请参阅此comment by Bjarne Stroustrup:
...根据标准,可以评估constexpr函数 编译器时间或运行时间,除非它用作常量表达式, 在这种情况下,它必须在编译时进行评估。保证 编译时评估,我们必须使用它在一个常量 表达是必需的(例如,作为数组绑定或作为案例标签)或 用它来初始化constexpr。我希望没有自尊心 编译器会错过优化机会来做我的事情 最初说:“如果在编译时评估constexpr函数 它的所有参数都是常量表达式。“
答案 3 :(得分:1)
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;