Back: Runtime Type Identification (RTTI)
Forward: Default template arguments
 
FastBack: Exceptions
Up: Changeable C++
FastForward: Compiler Quirks
Top: Autoconf, Automake, and Libtool
Contents: Table of Contents
Index: Index
About: About this document

16.2.10 Templates


Templates--known in other languages as generic types---permit you to write C++ classes which represent parameterized data types. A common application for class templates is container classes. That is, classes which implement data structures that can contain data of any type. For instance, a well-implemented binary tree is not interested in the type of data in its nodes. Templates have undergone a number of changes since their initial inclusion in the ARM. They are a particularly troublesome C++ language element in that it is difficult to implement templates well in a C++ compiler.

Here is a fictitious and overly simplistic C++ class template that implements a fixed-sized stack. It provides a pair of methods for setting (and getting) the element at the bottom of the stack. It uses the modern C++ template syntax, including the new typename keyword (see section 16.2.8 The typename Keyword).

 
template <typename T> class Stack
{
public:
  T first () { return stack[9]; }
  void set_first (T t) { stack[9] = t; }

private:
  T stack[10];
};

C++ permits this class to be instantiated for any type you like, using calling code that looks something like this:

 
int
main ()
{
  Stack<int> s;
  s.set_first (7);
  cout << s.first () << endl;
  return 0;
}

An old trick for fashioning class templates is to use the C preprocessor. Here is our limited Stack class, rewritten to avoid C++ templates:

 
#define Stack(T) \
  class Stack__##T##__LINE__ \
  { \
  public: \
    T first () { return stack[0]; } \
    void set_first (T t) { stack[0] = t; } \
  \
  private: \
    T stack[10]; \
  }

There is a couple of subtleties being used here that should be highlighted. This generic class declaration uses the C preprocessor operator `##' to generate a type name which is unique amongst stacks of any type. The __LINE__ macro is defined by the preprocessor and is used here to maintain unique names when the template is instantiated multiple times. The trailing semicolon that must follow a class declaration has been omitted from the macro.

 
int
main ()
{
  Stack (int) s;
  s.set_first (7);
  cout << s.first () << endl;
  return 0;
}

The syntax for instantiating a Stack is slightly different to modern C++, but it does work relatively well, since the C++ compiler still applies type checking after the preprocessor has expanded the macro. The main problem is that unless you go to great lengths, the generated type name (such as Stack__int) could collide with other instances of the same type in the program.



This document was generated by Gary V. Vaughan on February, 8 2006 using texi2html