previous page
next page

The Need for Templates

Imagine a simple bounds-checked array class:

#define MAX_ELEMS 8

class Array {
public:
  long& operator[](size_t n) {
    if( n < 0 || n >= MAX_ELEMS ) throw "out of bounds!";
    return m_rg[n];
  }

protected:
  long m_rg[MAX_ELEMS];
};

This class makes quiet, hard-to-find errors loud and easy to find:

void main(int argc, char* argv[]) {
  long rg[8]; // Built in array type
  rg[8] = 1;  // will corrupt the stack, but quietly

  Array array;  // Bounds-checked array type
  array[8] = 1; // will complain loudly
}

The bounds-checking part of the Array class really has nothing to do with the data being managed; using a little bit of C++ trickery, this is even easier to spot:

typedef long T;
class Array {
public:
  T& operator[](size_t n) {
    if( n < 0 || n >= MAX_ELEMS ) throw "out of bounds!";
    return m_rg[n];
  }

protected:
  T m_rg[MAX_ELEMS];
};

Notice that we've replaced the use of long with a generic type T. Unfortunately, this trick doesn't allow us to reuse the Array class with different types of T. When the compiler sees the Array class, it won't let us change T and compile it again with another type T. To get any reuse out of the Array class as it is, we have to do some cut-and-paste work and create different Array classes, one for each type we're interested in managing:

class ArrayOfChar {
public:
  char& operator[](size_t n);

protected:
  char m_rg[MAX_ELEMS];
};

class ArrayOfLong {
public:
  long& operator[](size_t n);

protected:
  long m_rg[MAX_ELEMS];
};

Besides the tedium involved with this technique, the developer of the Array family of classes would have to build an Array class for every type that the user of the class would want to manage. Because some of these types can be defined after the Array class is built, this is an especially difficult task. We'd like the compiler to step in and help us. And so it will, with templates.


previous page
next page
Converted from CHM to HTML with chm2web Pro 2.75 (unicode)