Template Metaprogramming

Introduction

In C++, template metaprogramming (TMP) is a programming technique that uses templates to perform computations at compile time.

First Steps

In a typical C++ program you have functions taking a series of arguments and performing some operations based on the value of these arguments. The question we try to solve in this tutorial is how do we use the C++ template system to perform operations like a typical C++ function does.

First consider the two following pieces of code. The first one is a function call and the second one is a template instantiation.

add(2, 5);
adder<int, int> anAdder;

Looking at the code you can see that it seems possible to interpret a template instantion as a function call where the arguments are delimited by square brackets instead of parentheses. However it is also different because the template instantiation doesn't return a value that you can assign to a variable for instance. Instead it produces a type.

But if we are to do computation with templates we somehow need to be able to extract a result from that computation. This is easy to achieve. The following piece of code shows how this can be done.

 File: main.cpp
#include <iostream>

template<bool v>
class BooleanType
{
public:
    static const bool value = v;
};

int main()
{
    std::cout << std::boolalpha << BooleanType<true>::value << std::endl;
    std::cout << std::boolalpha << BooleanType<false>::value << std::endl;
}

If you look at the expression BooleanType<true>::value we now have something that takes as argument a regular boolean value and returns another boolean value. And this was achieved easily by having a templated class with a public data member.

Note that this is also shows how we can easily convert between a value and a type and vice versa. In this particular example we start with a boolean value and create a type from it: either BooleanType<true> or BooleanType<false>. And we can use the value variable to get the initial boolean value back. The type and the boolean value store the same information. It's important not to get confused at this stage. The templated class doesn't represent the bool type, it represents a "boolean true" type or "boolean false" type, these are 2 different types in much the same way true and false are 2 different values. More on this in the next section.

So far we haven't still really written a proper function though since the previous example looks a bit too much like we're just storing a value. Let's look at the next example which is a trivial modification of the previous one. We now negate the template argument before storing it in the value static variable. By doing so we have actually written a negation function.

 File: main.cpp
#include <iostream>

template<bool v>
class NegatedBooleanType
{
public:
    static const bool value = !v;
};

int main()
{
    std::cout << std::boolalpha << NegatedBooleanType<true>::value << std::endl;
    std::cout << std::boolalpha << NegatedBooleanType<false>::value << std::endl;
}

References