Why doesn't clang calculate fibonacci (500) with the fibonacci version of constexpr?
I tried with constexpr
:
#include <iostream>
constexpr long long fibonacci(const int x)
{
return x <= 1 ? 1 : fibonacci(x - 1) + fibonacci(x - 2);
}
int main()
{
const long long lol = fibonacci(500);
std::cout << lol << std::endl;
}
So I want to be lol
computed at compile time:
toogy@stewie
ยป g++ -std=c++14 -g src/test.cc -o test.out
toogy@stewie
ยป ./test.out
4859788740867454402
It works great with g++
. When compiled, it even makes some flashbacks by optimizing this crappy fibonnaci function and then calculating instantly fibonacci(500)
.
Then I try to use clang++
:
toogy@stewie
ยป clang++ -std=c++1y -g src/test.cc -o test.out
toogy@stewie
ยป ./test.out
... very long
lol
not evaluated at compile time clang++
(proven gdb
). Why?
source to share
It strikes the maximum depth of recursion. You can force the lol
evaluation at compile time by doing it constexpr
, that is:
constexpr long long lol = fibonacci(500);
Doing this and compiling with clang++ -std=c++11 t.cpp
gives errors:
t.cpp:10:25: error: constexpr variable 'lol' must be initialized by a constant
expression
constexpr long long lol = fib(500);
^ ~~~~~~~~
t.cpp:4:1: note: constexpr evaluation hit maximum step limit; possible infinite
loop?
{
^
t.cpp:5:38: note: in call to 'fib(4)'
return x <= 1 ? 1 : fib(x - 1) + fib(x - 2);
^
t.cpp:5:25: note: in call to 'fib(6)'
return x <= 1 ? 1 : fib(x - 1) + fib(x - 2);
^
t.cpp:5:38: note: in call to 'fib(7)'
return x <= 1 ? 1 : fib(x - 1) + fib(x - 2);
^
t.cpp:5:25: note: in call to 'fib(9)'
return x <= 1 ? 1 : fib(x - 1) + fib(x - 2);
^
t.cpp:5:25: note: in call to 'fib(10)'
t.cpp:5:25: note: (skipping 480 calls in backtrace; use
-fconstexpr-backtrace-limit=0 to see all)
t.cpp:5:25: note: in call to 'fib(496)'
t.cpp:5:25: note: in call to 'fib(497)'
t.cpp:5:25: note: in call to 'fib(498)'
t.cpp:5:25: note: in call to 'fib(499)'
t.cpp:10:31: note: in call to 'fib(500)'
constexpr long long lol = fib(500);
^
1 error generated.
Clang cannot (with the default compiler flags, although I still couldn't compile it with -fconstexpr-depth=1000000000
(that's 1 billion)) evaluate fibonacci(500)
at compile time, so instead it is executed at runtime with the code you posted. From @Streppel's link you can increase the max recursion depth for constant expressions using a flag -fconstexpr-depth=N
.
That said, the 500th Fibonacci number is huge *, so this is definitely an overflow, which means undefined behavior for signed integers (so all bets are actually off). ( But you can do this if you are using template metaprogramming )
* as in 105 digits huge : 139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125
source to share