Question

I want to compare meta programming and use of constexpr in c++0x. then I write a fib function in both model. when I use meta programming model, answer print out very fast because it calculated in compile time. but when I use constexpr funcion it calculate value in run time, not in compile time. I using g++( gcc ) 4.8 .can any body help me?

#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;
}
Was it helpful?

Solution

I believe the reason is that constexpr is not guaranteed to execute at compile-time. To enforce compile-time evaluation, you have to assign it to a compile-time alias. Like,

enum {i = fib(NUM)};

OTHER TIPS

With gcc, at least, you can get the constexpr value to be computed at compile time by making it a static variable:

static const unsigned fibNUM = fib(NUM);

As I read the standard, it's still allowed to compute the value at startup, but in practice it will be computed at compile time.

A simple test to see if your constexpr are really being done at compile-time is to use an std::array:

#include <array>

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

gcc has no complaints.

See this comment by Bjarne Stroustrup:

... according to the standard a constexpr function may be evaluated at compiler time or run time unless it is used as a constant expression, in which case it must be evaluated at compile-time. To guarantee compile-time evaluation, we must either use it where a constant expression is required (e.g., as an array bound or as a case label) or use it to initialize a constexpr. I would hope that no self-respecting compiler would miss the optimization opportunity to do what I originally said: "A constexpr function is evaluated at compile time if all its arguments are constant expressions."

constexpr is not guaranteed to be evaluated at compile time. This means, compiler can choose whether to evaluate at compile time or at run time. You can try to assign it to a compile time constant and check like this...

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;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top