How does C++ keep track of which overloaded function is which? It assigns a secret identity to each of these functions. When you use the editor of your C++ development tool to write and compile programs, your C++ compiler performs a bit of magic on your behalf—known as
long MyFunctionFoo(int, float);
This format is fine for us humans; we know that the function accepts two arguments of type int and float, and it returns a value of type long. For its own use, the compiler documents this interface by transforming the name into an internal representation with a more unsightly appearance, perhaps something like this:
?MyFunctionFoo@@YAXH
The apparent gibberish decorating the original name (or mangling it, depending on your attitude) encodes the number and types of parameters. A different function signature would result in a different set of symbols being added, and different compilers would use different conventions for their efforts at decorating.
Function Templates
Contemporary C++ compilers implement one of the newer C++ additions: function templates. A
Earlier Listing 8.4 defined a function that swapped two int values. Suppose you want to swap two double values instead. One approach is to duplicate the original code but replace each int with double. If you need to swap two char values, you can use the same technique again. Still, it’s wasteful of your valuable time to have to make these petty changes, and there’s always the possibility of making an error. If you make the changes by hand, you might overlook an int. If you do a global search-and-replace to substitute, say, double for int, you might do something such as converting
int x;
short interval;
to the following:
double x; // intended change of type
short doubleerval; // unintended change of variable name
C++’s function template capability automates the process, saving you time and providing greater reliability.
Function templates enable you to define a function in terms of some arbitrary type. For example, you can set up a swapping template like this:
template
void Swap(AnyType &a, AnyType &b)
{
AnyType temp;
temp = a;
a = b;
b = temp;
}
The first line specifies that you are setting up a template and that you’re naming the arbitrary type AnyType. The keywords template and typename are obligatory, except that you can use the keyword class instead of typename. Also you must use the angle brackets. The type name (AnyType, in this example) is your choice, as long as you follow the usual C++ naming rules; many programmers use simple names such as T, which, one must admit, is simple indeed. The rest of the code describes the algorithm for swapping two values of type AnyType. The template does not create any functions. Instead, it provides the compiler with directions about how to define a function. If you want a function to swap ints, then the compiler creates a function following the template pattern, substituting int for AnyType. Similarly, if you need a function to swap doubles, the compiler follows the template, substituting the double type for AnyType.
Before the C++98 Standard added the keyword typename to the language, C++ used the keyword class in this particular context. That is, you can write the template definition this way:
template
void Swap(AnyType &a, AnyType &b)
{
AnyType temp;
temp = a;
a = b;
b = temp;
}
The typename keyword makes it a bit more obvious that the parameter AnyType represents a type; however, large libraries of code have already been developed by using the older keyword class. The C++ Standard treats the two keywords identically when they are used in this context. This book uses both forms so that you will be familiar with them when encountering them elsewhere.
Tip
You should use templates if you need functions that apply the same algorithm to a variety of types. If you aren’t concerned with backward compatibility and can put up with the effort of typing a longer word, you can use the keyword typename rather than class when you declare type parameters.