Template metaprogramming
From Cppwiki
Template metaprogramming is a form of compile-time programming in C++, using template expressions. While a normal program would use variables of a certain type, in metaprogramming, types are variables. A metaprogram is very similar to the style of programming used in functional programming.
Functions in metaprogramming are called metafunctions. The simplest metafunction simply returns a value with no inputs; i.e. a constant. An integer constant function could be written thus:
template<typename T, T n>
struct int_ {
static T const value = n;
typedef T type;
};
We can then express constant types such as int_<int, 4> and int_<unsigned long, 42>.
std::cout << int_<int, 4>::value << '\n'; // prints 4
A simple metafunction with inputs might be one to add two ints. A first try at such a function might look like this:
template<typename T, T a, T b>
struct plus {
static T const value = a + b;
typedef T type;
};
Although this would indeed work as desired, it has a few problems. Firstly, 'a' and 'b' are required to be integral constants; plus<int_<int, 1>, int_<int, 2> > will not work. In this case one could write plus<int, int_<int, 1>::value, int_<int, 2>::value>, but the requirement to reduce all inputs to integral types quickly becomes a pain, particularly since plus<> might be specialised over types which cannot be represented as such.
Instead, metafunctions are written using inheritance. In a functional language, plus would probably be written as something equivalent to:
plus (a, b) = a + b
This effectively says that plus(a,b) is a+b; in C++, the closet equivalent is:
template<typename a, typename b>
struct plus : int_<typename a::type, a::value + b::value> {}
Here we state that plus<a,b> is-a int<a+b>. Other than the values being types instead of variables, this is effectively identical to the functional program.
Examples
A 'pair' metaclass, which returns a type storing two other types; plus<> is specialised such that plus(pair(a, b), pair(c, d)) = pair(a + c, b + d).
#include <iostream>
template<typename T, int n>
struct int_ {
typedef T type;
static const T value = n;
};
template<typename a, typename b>
struct plus : int_<typename a::type, a::value + b::value> {};
template<typename a, typename b>
struct pair {
typedef a first;
typedef b second;
};
template<typename af, typename as, typename bf, typename bs>
struct plus<pair<af, as>, pair<bf, bs> > :
pair< plus<af, bf>,
plus<as, bs>
>
{};
int main() {
typedef int_<int, 42> a;
typedef int_<int, 3> b;
typedef pair<int_<int, 1>, int_<int, 1> > pt;
std::cout << plus<a, b>::value << '\n';
typedef plus<pair<a, b>, pt> res; std::cout << res::first::value << ", " << res::second::value << '\n'; }
A mathematical power function can be computed at compile-time with template metaprogramming.
template< int base, unsigned exponent >
struct power {
enum { value = base * power<base, exponent - 1>::value };
};
template< int base >
struct power<base,0> {
enum { value = 1 };
};