Autoconf, Automake, and Libtool: Templates

| ### 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