- Learn C++ Test Site - https://test.learncpp.com -

14.3 — Template classes

In the previous two lessons, you learn how function templates [1] and function template instances [2] could be used to generalize functions to work with many different data types. While this is a great start down the road to generalized programming, it doesn’t solve all of our problems. Let’s take a look at an example of one such problem, and see what templates can do for us further.

Templates and container classes

In the lesson on container classes [3], you learned how to use composition to implement classes that contained multiple instances of other classes. As one example of such a container, we took a look at the IntArray class. Here is a simplified example of that class:

While this class provides an easy way to create arrays of integers, what if we want to create an array of doubles? Using traditional programming methods, we’d have to create an entirely new class! Here’s an example of DoubleArray, an array class used to hold doubles.

Although the code listings are lengthy, you’ll note the two classes are almost identical! In fact, the only substantive difference is the contained data type. As you likely have guessed, this is another area where templates can be put to good use to free us from having to create classes that are bound to one specific data type.

Creating template classes is works pretty much identically to creating template functions, so we’ll proceed by example. Here’s the IntArray classes, templatated version:

As you can see, this version is almost identical to the IntArray version, except we’ve added the template declaration, and changed the contained data type from int to T.

Note that we’ve also defined the GetLength() function outside of the class declaration. This isn’t necessary, but new programmers typically stumble when trying to do this for the first time due to the syntax, so an example is instructive. Each templated member function declared outside the class declaration needs its own template declaration. Also, note that the name of the templated array class is Array<T>, not Array -- Array would refer to a non-templated version of a class named Array.

Here’s a short example using the above templated array class:

This example prints the following:

11     11.5
10     10.5
9       9.5
8       8.5
7       7.5
6       6.5
5       5.5
4       4.5
3       3.5
2       2.5
1       1.5
0       0.5

Templated classes are instanced in the same way templated functions are -- the compile stencils a copy upon demand with the template parameter replaced by the actual data type the user needs and then compiles the copy. If you don’t ever use a template class, the compile won’t even compile it.

Template classes are ideal for implementing container classes, because it is highly desirable to have containers work across a wide variety of data types, and templates allow you to do so without duplicating code. Although the syntax is ugly, and the error messages can be cryptic, template classes are truly one of C++’s best and most useful features.

A note for users using older compilers

Some older compilers (eg. Visual Studio 6) have a bug where the definition of template class functions must be put in the same file as the template class is defined in. Thus, if the template class were defined in X.h, the function definitions would have to also go in X.h (not X.cpp). This issue should be fixed in most/all modern compilers.

14.4 -- Expression parameters and template specialization [4]
Index [5]
14.2 -- Function template instances [2]