In general, templates are patterns, models, or outlines. An example of a template is a word processing file containing the basic format of a specialized document that writers use as a starting point. Writes use the template by filling in some specific or missing information. C++ template functions similarly provide the function's basic pattern or format while allowing programmers to provide one or more unspecified data types.
For example, the steps for swapping two array elements (a sub-task of sorting an array) are always the same, independent of the element type. The first presentation of the swapping problem demonstrated that a solution requires a temporary variable, whether implemented "inline" or as a function, requiring a data type as part of its definition. A function implementation further requires two parameter definitions, including their types. A large set of overloaded functions can handle the fundamental data types (char, double, etc.) but not application classes, structures, or enumerations. Templates allow programmers to create a generic swap function.
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.
The yellow-highlighted text is "boilerplate code" signaling the beginning of a template function definition to the compiler and introducing the template variable, T. The capital letter T is the traditional 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 compiler compiles the application code using the function, replacing the T with a fundamental or program-created data type.
The original, still valid syntax, used the class keyword to begin template functions.
Modern C++ adds the typename keyword to the templating mechanism, making both keywords valid.
The compiler determines the replacement type from the application program's data.
In the first (light blue) example, the application passes two elements from a double array, replacing T with double.
The second (light red) example assumes that Person is an application class. So, passing two elements of the people array replaces T with Person.
How C++ compiles template functions differs from how it processes "regular" or non-template functions. The compiler compiles regular functions to machine code, which the linker or loader can link to one or more application programs in the future. However, when substituting a type name for the template variable, the compiler can't make the substitution independently of the application using it, implying that the compiler must compile the template function and application code simultaneously. Therefore, it's impossible to compile template functions and store the object code in a system library like sqrt and pow. C++ provides template functions as source code in header files, which application programs #include, so they are compiled with the application.
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. If the application uses the template function with multiple data types, each type results in a different substitution, one for each type. For example, Figure 1(c) shows the swap function used with both an array of integers and an array of Person objects. In the first example, int replaces T, while in the second example, Person replaces it. Each replacement results in a separate copy of the swap function source code in the program, one copy processing int values and the second processing Person objects.
<algorithm>: The Template Function Library
C++ provides numerous template functions, prototyped in the <algorithm> header file. There are too many to describe in detail, so we focus on one as an example. 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.
<algorithm> Examples
The textbook version, (a < b) ? a : b, and the linked online version, !(b < a) ? a : b, are similar but not identical. The difference between the two versions' tests (the conditional operator's first operand) is subtle and often irrelevant. The two versions behave differently only when a == b. In this case, the textbook version returns b while the online version returns a. But, since the two are equal, does it matter which value the function returns?
Alone, returning b rather than a is irrelevant. However, the difference may become relevant when the min function is part of a more complex operation, such as sorting an array's elements. A sorting algorithm is said to be stable (an often desirable characteristic) if it doesn't change the relative order of equal elements. For example, if a precedes b in an unsorted array, a stable sorting algorithm will preserve that relative order in the sorted array. If the sorting function calls min, the online version maintains the sorting operation's stability, while the textbook's simpler version does not.