13.1. Introduction To Templates

C++ is an extensible language, which means that it is possible to add new data types to the language without modifying the compiler or the syntax that the compiler recognizes and processes. Although extensibility is a powerful feature, it does make it more difficult to create library functions. Library functions are general solutions to common problems that application programmers use whenever they encounter one of those problems. For example, the sqrt and pow functions date to the early days of the C programming language. C++ inherits both functions, places them in a library included with the compiler, where they are available whenever a programmer needs to find a square root or raise a number to a power.

Library functions are often tied tightly to specific data types. For example, in the 1990 ANSI C standard (and before that time when there was no ANSI C standard), there was only one square root function available in the library:

double sqrt(double x);

The ANSI 1999 C standard added two more versions of the square root function:

float sqrtf(float x);
long double sqrtl(long double x);

C++'s ability to overload functions allowed compilers to consolidate the three into one overloaded function in the ANSI 1998 C++ standard math library:

double sqrt(double x);
float sqrt(float x);
long double sqrt(long double x);

If we restrict ourselves to the fundamental, built-in data types, it's possible to create a short, exhaustive list of overloaded functions that perform the same operation but that operate on different data types. For example:

char	min(char x, char y);
short	min(short x, short y);
int	min(int x, int y);
long	min(long x, long y);
float	min(float x, float y);
double	min(double x, double y);
A family of functions. Each overloaded function in the family finds and returns the smallest of two argument values. The argument data types determine which overloaded function is called.

Such library functions are frequently written and included with the compiler. But these functions are completed long before application programmers begin designing and implementing new data types. For example, we can create a new data type as a class named fraction. It's quite possible that we may want to find the smallest of two fraction objects, but none of the min functions listed above are overloaded for the fraction class.

One solution, used in the past, was to implement general functions as macros, which are somewhat more type-independent than traditional functions. We could write min as a macro:

#define min(x,y)	((x < y) ? (x) : (y))

The macro might work in simple cases if the fraction class overrides operator<. Still, macros are fraught with other problems, as chapter 6 illustrates. We need a programming technique that embraces C++'s extensibility by providing a way to generalize the data types that a function accepts and processes while still allowing a programmer to deal with the subtleties of new, often aggregate, data types. Containers (called collections in Java) are data structures that store data. Linked lists and binary trees are two common examples. Can we also generalize the data types that they store? Templates elegantly solve these problems.

C++ templates look and behave like Java's generic classes. Furthermore, templates and generic classes are used to solve the same problems in both languages. However, C++ is a hybrid language that supports both the procedural and the object-oriented programming paradigms - where Java only supports the object-oriented paradigm. As a consequence, C++ programmers can also use templates with non-member functions.