I'm using gcc 4.6.1 and am getting some interesting behavior involving calling a constexpr
function. This program runs just fine and straight away prints out 12200160415121876738
.
#include <iostream>
extern const unsigned long joe;
constexpr unsigned long fib(unsigned long int x)
{
return (x <= 1) ? 1 : (fib(x - 1) + fib(x - 2));
}
const unsigned long joe = fib(92);
int main()
{
::std::cout << "Here I am!\n";
::std::cout << joe << '\n';
return 0;
}
This program takes forever to run and I've never had the patience to wait for it to print out a value:
#include <iostream>
constexpr unsigned long fib(unsigned long int x)
{
return (x <= 1) ? 1 : (fib(x - 1) + fib(x - 2));
}
int main()
{
::std::cout << "Here I am!\n";
::std::cout << fib(92) << '\n';
return 0;
}
Why is there such a huge difference? Am I doing something wrong in the second program?
Edit: I'm compiling this with g++ -std=c++0x -O3
on a 64-bit platform.
constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.
A constexpr function that is eligible to be evaluated at compile-time will only be evaluated at compile-time if the return value is used where a constant expression is required. Otherwise, compile-time evaluation is not guaranteed.
The principal difference between const and constexpr is the time when their initialization values are known (evaluated). While the values of const variables can be evaluated at both compile time and runtime, constexpr are always evaluated at compile time.
#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.
I also wanted to see how gcc did optimize the code for this new constexpr keyword, and actually it's just because you are calling fib(92) as parameter of the ofstream::operator<<
::std::cout << fib(92) << '\n';
that it isn't evaluated at the compilation time, if you try calling it not as a parameter of another function (like you did in)
const unsigned long joe = fib(92);
it is evaluated at compile time, I did a blog post about this if you want more info, I don't know if this should be mentioned to gcc developers.
joe
is an Integral Constant Expression; it must be usable in array bounds. For that reason, a reasonable compiler will evaluate it at compile time.
In your second program, even though the compiler could calculate it at compile time, there's no reason why it must.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With