Reputation: 439
I wonder about the next code.
#include <iostream>
using std::cout;
template<int N> struct Fib {
enum { v = Fib<N - 1>::v + Fib<N - 2>::v };
};
template<> struct Fib<0> {
enum { v = 0 };
};
template<> struct Fib<1> {
enum { v = 1 };
};
int fib(int n) {
return n < 2 ? n : fib(n - 1) + fib(n - 2);
}
int main() {
cout << Fib<46>::v << '\n';
// cout << fib(46) << '\n';
return 0;
}
It calculates the result at the compilation time without any noticeable delay. How is it possible? If we use the call to fib(46) we will have to wait for several seconds even with the fastest PC. The template uses the same schema of calculation and it makes it instantly. I am also surprised by the fact that the size of the executable file produced with the template is almost the same as without template. I used GCC.
Upvotes: 5
Views: 360
Reputation: 2355
They are not fast, they are already there.
If you manage to write such a template program the value that you're using will be there before the program starts.
This can be also achieved with constexpr
.
However, the fact that you need all the information at compile time is making it
applicable to a very few use cases.
I've reworked your example to show you that(link to example).
main:
.LFB0:
.file 1 "/tmp/compiler-explorer-compiler118417-63-1cf1gj5.e1tp/example.cpp"
.loc 1 12 0
.cfi_startproc
.loc 1 14 0
mov eax, 1836311903
ret
The eax
is filled with the number 1836311903
which happens to be exactly the 46th fibonnaci number.
Upvotes: 1
Reputation: 14589
fib()
is a recursive function which is bad for performance in this case, because of multiple iterations of function call and stack creation.
Template value would be calculate value statically, because N is known at compile time. Also try:
constexpr int fib(int n) {
return n < 2 ? n : fib(n - 1) + fib(n - 2);
}
This would make it equivalent of template solution, value of function would be calculated in compile time if possible) with -O2 flag :P
Upvotes: 0
Reputation: 85351
It's due to inherent memoization in the template solution.
During compilation, each instantiation like Fib<1>
, Fib<2>
, etc, is performed (by the compiler) only once and remembered.
When you run fib(n)
on the other hand, fib(1)
, fib(2)
, etc. are calculated many times. The solution could be to memoize it, i.e. remember the result of each fib
call in a map or an array, and return that if a result already exists.
Upvotes: 17