13.3. More Features

13.3.1. Smart Pointers

In contrast to most "modern" languages covered in this book (including good old Lisp), C++ leaves memory management to the developer. However, it is easier to hide the complexity of memory management in C++. We have already seen the standard implementations of strings and collections that manage the memory of the underlying data structures transparently.

13.3.2. Metaprogramming

When discussing C we have seen how to extend the C language using textual substitution with macros. In principle, C++ templates provide the same thing in a more structured, type-safe fashion. But as it turns out, the C++ template mechanism can be used to extend the C++ language in surprising ways.

The basic idea behind template metaprogramming is to use templates with non-type parameters as functions which are evaluated at compile time. Here is a simple example (see Gurtovoy>) computing the factorial function at compile time.

#include <iostream>

template<unsigned n>
struct factorial {
  static const unsigned value = n * factorial<n-1>::value;
};

template<>
struct factorial<0> {
  static const unsigned value = 1;
};

int main() {
  factorial<5> fac5;
  std::cout << fac5.value << std::endl;
  return 0;
}

--> 120

The "template function" or "metafunction" factorial is defined recursively using the unsigned parameter n. The constant class attribute value plays the role of the return value. The important part to notice is that the recursion is evaluated at compile time when instantiating the template factorial<5>. After this example, it is not surprising that C++ templates can theoretically solve any computable problem (that is, they are turing-complete).

In contrast to metaprogramming in the Lisp-like languages, template metaprogramming in C++ is totally different from the normal (non-template, procedural or object-oriented) programming in C++. In fact, it looks more like functional programming in ML using pattern matching and recursion.