Function templates
In drawAll( ) you see
something new. So far in this chapter, we have been using only
class templates, which
instantiate new classes based on one or more type parameters. However, you can
as easily create function
templates, which create new functions based on type parameters. The reason
you create a function template is the same reason you use for a class template:
You’re trying to create generic code, and you do this by delaying the
specification of one or more types. You just want to say that these type
parameters support certain operations, not exactly what types they
are.
The
function template drawAll( ) can be thought of as an
algorithm (and this is what most of the function templates in the
Standard C++ Library are called). It just says how to do something given
iterators describing a range of elements, as long as these iterators can be
dereferenced, incremented, and compared. These are exactly the kind of iterators
we have been developing in this chapter, and also – not coincidentally
– the kind of iterators that are produced by the containers in the
Standard C++ Library, evidenced by the use of vector in this example.
We’d also like
drawAll( ) to be a generic algorithm,
so that the containers can be any type at all and we don’t have to write a
new version of the algorithm for each different type of container. Here’s
where function templates are essential, because they automatically generate the
specific code for each different type of container. But without the extra
indirection provided by the iterators, this genericness wouldn’t be
possible. That’s why iterators are important; they allow you to write
general-purpose code that involves containers without knowing the underlying
structure of the container. (Notice that, in C++, iterators and generic
algorithms require function templates in order to work.)
You can see the proof of this in
main( ), since drawAll( ) works unchanged with each
different type of container. And even more interesting, drawAll( )
also works with pointers to the beginning and end of the array sarray.
This ability to treat arrays as containers is integral to the design of the
Standard C++ Library, whose algorithms look much like
drawAll( ).
Because container class
templates
are rarely subject to the inheritance and upcasting you see with
“ordinary” classes, you’ll almost never see virtual
functions in container classes. Container class reuse is implemented with
templates, not with
inheritance.