In general, a template is a pattern or model. An example of a template is a (word processing) file that contains the basic format of a specialized document that writers use as a starting point. We use the template by filling in some specific or missing information. A C++ template function similarly provides a function's basic pattern or format. We can use the function by providing (a) any unspecified data types and (b) any data values (i.e., function arguments).
For example, suppose that we need to write a swap function that swaps the values stored in two variables (this task is a vital sub-operation used by functions that sort data stored in an array). It would be nice if our function worked with all arrays regardless of the kind or type of data stored in the array. Based on C++ templates, we can write and use a general, type-independent swap function as illustrated in Figure 1:
template <class T>
void swap(T& x, T& y)
{
T temp = x;
x = y;
y = temp;
}
template <typename T>
void swap(T& x, T& y)
{
T temp = x;
x = y;
y = temp;
}
double data[1000];
. . .
swap(data[i], data[j]);
. . .
person people = new person[100];
. . .
swap(people[x], people[y]);
(a)
(b)
(c)
Defining and calling a template-based swap function. It is traditional to use a capital T to represent the template variable when there is only one. T is a placeholder for some general, yet-to-be-determined data type. The data type is determined later when the user calls the function, at which time the T in the function is replaced by the specific data type derived from the variables used in the function call. The syntax highlighted in yellow represents "boiler plate" code that is always present (it is the code that the C++ designers chose to use to introduce the template mechanism).
The original syntax, which still works, used the keyword class to introduce the template variable
Newer syntax also allows the keyword typename to introduce the template variable because any data type, not just class names, can replace T
The compiler determines from the function calls that the arguments are type double in the first call and are type person in the second call (where person presumably names a class or structure).
Template functions share another important connection with parameterized macros: we must wait until the type substitution is complete before compiling them. It is impossible to compile template functions and store the object code in a system library like sqrt and pow. That doesn't mean that we can't or don't have libraries of template functions, but it does mean that template functions are provided as source code.
C++ libraries put template function source code in a header file, programmers include it with "normal" source code, and the compiler processes it following the type expansion or substitution. Furthermore, the compiler expands the template source code for each data type used with a template function. So, a program contains one copy of the code for each data type that the program needs the function to support. For example, Figure 1(b) shows the swap function used with both an array of integers and an array of person objects. In the first example, int replaces the function template variable, and in the second example, the class name person replaces the function template variable. Each replacement results in a separate copy of the swap function source code with int and person replacing the template variable T respectively.
<algorithm>: The Template Function Library
C++ does provide a rich set of template functions, which are contained in the <algorithm> header file. The min function (near the bottom of the list) is just one of many template functions C++ programmers may utilize. The complexity and flexibility of these functions have steadily increased since their introduction with the ANSI 1998 C++ standard. For example, two simple but quite useful versions of the min template function are:
template <class T> const T& min (const T& a, const T& b);
template <class T, class Compare> const T& min (const T& a, const T& b, Compare comp);
The first function "assumes" that the type replacing T supports the < operator. So, if a class replaces T, the class must overload operator<. Figures 2 and 3 demonstrate this version of min. The second version of min uses an external comparator, which may be either a function pointer (demonstrated in Figure 4) or a function object (demonstrated in Figure 5).