The Joy of C++ Templates Metaprogramming

I am in charge (with 2 fellow snipers) of a lecture about Advanced Programming. This includes the C++ standard library and we will probably include some stuff regarding dynamic languages (how they work, functional-style features like closures or continuations, and so on). This morning, I had a look at C++ templates metaprogramming.

In fact, not that many people know about C++ templates metaprogramming. It has many funny use-cases, including loops unrolling and performing computations at compile-time rather than at runtime. It is also at the heart of many parts of the STL and libraries such as the Boost ones.

I would not use it for everything as it is quite a tricky way of writing programs. In fact, it either compiles fine, or you most probably get errors and warnings that you just can’t understand at all :-)

Here is an example that I wrote this morning:

#include<iostream>
 
using namespace std;
 
template<int N> struct Fibo
{
  static const unsigned long long
    value = Fibo<N - 1>::value + Fibo<N -2>::value;
};
 
template<> struct Fibo<1>
{
  static const unsigned long long value = 1;
};
 
template<> struct Fibo<0>
{
  static const unsigned long long value = 0;
};
 
template<int N> void unroll_fibo()
{
  unroll_fibo<N - 1>();
  cout << Fibo<N>::value << endl;
}
 
template<> void unroll_fibo<0>()
{
  cout << Fibo<0>::value << endl;
}
 
int main()
{
  unroll_fibo<60L>();
  return 0;
}

It computes the Fibonacci number. In fact when you run it, you will get the Fibonacci numbers from 0 to 60 instantly! It leverages the two techniques mentionned above: loops unrolling and compile-time computations.

By constrast, the following is a more traditional way of computing the Fibonacci numbers… and the execution time is not even comparable (it has not finished after 3 minutes on my G4 processor).

#include <iostream>
 
using namespace std;
 
long long fibo(const long long &n)
{
  if (n == 0L)
  {
    return 0L;
  }
  else if (n == 1L)
  {
    return 1L;
  }
  else
  {
    return fibo(n - 1) + fibo(n - 2);
  }
}
 
void display_fibo(const int &max)
{
  for (int i = 0; i <= max; ++i)
  {
    cout << fibo((long long) i) << endl;
  }
}
 
int main()
{
  display_fibo(60);
  return 0;
}

Funny isn’t it? ;-)

7 Responses to “The Joy of C++ Templates Metaprogramming”

  1. Pierre CNo Gravatar says:

    Hello Julien,

    Did you give a look at this wonderful website : http://ktd.club.fr/programmation/cpp-metaprog.php

    (Ouille mes chevilles)

    +
    Chacha

  2. BoyanNo Gravatar says:

    The power of meta programming comes (among other things) from the fact that it’s value-free, ie. everything is calculated during compile-time and run-time memory requirements are zero.
    Which is not true in your case.
    Try replacing static member variable “value” with “enum{value=…}” for a start. Cleaning and simplifying the code would be next.

  3. JulienNo Gravatar says:

    @Boyan: Sorry but I don’t agree with your statements.

    “Which is not true in your case.”

    So please show me WHY it is wrong, as in this case everything is calculated at compile-time. Compile the source code and see for yourself… or explain me why the compiler does not perform the computations in this case.

    “Try replacing static member variable “value” with “enum{value=…}” for a start.”

    Yes, I know about enums, but the fact is that enum == int and I wanted to use long long integers rather than int. Having enum {value = …} or a static constant integer is actually the same…

    Enums are one way to do it, but many times you need to manipulate other data types.

    “Cleaning and simplifying the code would be next.”

    ???

    LOL :-)

  4. JulienNo Gravatar says:

    I guess you are the one whose DZone profile is http://www.dzone.com/users/profile/171944.html

    Great… you only give negative votes. I’m impressed ;-)

  5. OJNo Gravatar says:

    Off topic: So what if he only gives negative votes? He can vote how he wishes. Dzone is just a popularity contest anyway. It’s just a MySpace for developers. Get over it.

    On topic: Personally I find that template metaprogramming can be ‘handy’. But to date I’ve rarely (if ever) found a case where I’d consider using it in production code.

  6. FruNo Gravatar says:

    Julien,
    I don’t quite understand Boyan’s comment on “cleaning and simplifying”, but he *is* correct about your solution wasting memory.

    He didn’t say that your code didn’t compute the answer at compile-time (which it does). He said that your solution doesn’t have a zero run-time memory requirement - what he described as “value-free”. Because you’re using static variables inside each template instantiation, you will have at least “n” static variables (admittedly, they are const, but they still consume memory space in the program’s run time data segment), where each variable is initialized by the compiler’s compile time meta-template recursion to the value of Fib(n).

    If you use enums rather than static const variables inside your templates, then you wouldn’t use any memory at all.

  7. JulienNo Gravatar says:

    @Fru: thanks for the explanations, but I don’t quite get it why using enums would use less memory than static constants. My understanding is that for each instantiation of the template you still have a slot in memory for the enum value… or I am missing something? Please let me know :-)

    Even if enum where to consume less memory than constants, they still limit the application of such a technique to normal integer values, hence the need for static constants.

Leave a Reply