Tools.h++ Manual
13-2 104011 Tandem Computers Incorporated
13
Enter templates
Templates, or parameterized types, offer an elegant solution. Over the next
few years they promise to revolutionize the way we approach C++
programming. Indeed, 5 years from now the polymorphic collection approach
may be just a footnote in the history of C++ design.
Templates are extremely similar to the "generic.h" approach, described in the
following section, which relies on preprocessor macros to define a family of
classes parameterized on a type. However, a macro does a lexical substitution
in situ, that is at the site of invocation, making them extremely hard to debug (a
single line may be expanded into thousands of tokens!). They are also nasty to
write, requiring as they do that all newlines be escaped with a backslash.
Templates are logically a class declaration parameterized on a type. They are a
prescription for how a particular type of collection should behave. For
example, a Vector template would describe such things as how to index an
element, how long it is, how to resize, etc. The actual type of the elements is
independent of these larger, more general issues.
Now if you procede to request a vector of a particular type, say a
Vector<double>
, that is, a vector of doubles, then the compiler goes back to
the template declaration and fills it in for the type double. The effect is as if
you had hand written a class "
VectorOfDoubles
". But, of course, you didn't.
Instead, the compiler automatically generated the logical equivalent of such a
class. The result is extreme source code reuse.
What's the catch?
Which brings us to the one disadvantage of templates. It is the source code that
is being reused, not the object code. A declaration for
Vector<double>
gets
compiled separately from
Vector<int>
. Unless some provisions have been
made by the class designer, the two declarations will generate totally
independent object code, with the potential for bloat of the executable.
Indeed, to some extent, this is unavoidable. Still, the careful class designer will
recognize points of commonality that do not depend on the actual type and
factor them out. These are put in a separate "type-independent" class which
can be compiled once, resulting in more compact code. A trivial example, one
that builds on our discussion of vectors, might be the vector length. We might