Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

constexpr question, why do these two different programs run in such a different amount of time with g++?

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.

like image 347
Omnifarious Avatar asked Aug 15 '11 12:08

Omnifarious


People also ask

What is the point of constexpr?

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.

Is constexpr always evaluated at compile time?

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.

What is the difference between const and constexpr?

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.

Why is constexpr better than #define?

#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.


2 Answers

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.

like image 113
b3nj1 Avatar answered Oct 06 '22 15:10

b3nj1


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.

like image 44
MSalters Avatar answered Oct 06 '22 15:10

MSalters