Using compiler-generated int swapper:
Now i, j = 20, 10.
Original arrays:
07/04/1776
07/20/1969
Swapped arrays:
07/20/1969
07/04/1776
Template Limitations
Suppose you have a template function:
template
void f(T a, T b)
{...}
Often the code makes assumptions about what operations are possible for the type. For instance, the following statement assumes that assignment is defined, and this would not be true if type T is a built-in array type:
a = b;
Similarly, the following assumes > is defined, which is not true if T is an ordinary structure:
if (a > b)
Also the > operator is defined for array names, but because array names are addresses, it compares the addresses of the arrays, which may not be what you have in mind. And the following assumes the multiplication operator is defined for type T, which is not the case if T is an array, a pointer, or a structure:
T c = a*b;
In short, it’s easy to write a template function that cannot handle certain types. On the other hand, sometimes a generalization makes sense, even if ordinary C++ syntax doesn’t allow for it. For example, it could make sense to add structures containing position coordinates, even though the + operator isn’t defined for structures. One approach is that C++ allows one to overload the + operator so that it can be used with a particular form of structure or class. Chapter 11 discusses this facility. A template that requires using the + operator then could handle a structure that had an overloaded + operator. Another approach is to provide specialized template definitions for particular types. Let’s look at that next.
Explicit Specializations
Suppose you define a structure like the following:
struct job
{
char name[40];
double salary;
int floor;
};
Also suppose you want to be able to swap the contents of two such structures. The original template uses the following code to effect a swap:
temp = a;
a = b;
b = temp;
Because C++ allows you to assign one structure to another, this works fine, even if type T is a job structure. But suppose you only want to swap the salary and floor members, keeping the name members unchanged. This requires different code, but the arguments to Swap() would be the same as for the first case (references to two job structures), so you can’t use template overloading to supply the alternative code.
However, you can supply a specialized function definition, called an
The specialization mechanism has changed with the evolution of C++. We’ll look at the current form as mandated by the C++ Standard.
Third-Generation Specialization (ISO/ANSI C++ Standard)
After some youthful experimentation with other approaches, the C++98 Standard settled on this approach:
• For a given function name, you can have a non template function, a template function, and an explicit specialization template function, along with overloaded versions of all of these.
• The prototype and definition for an explicit specialization should be preceded by template <> and should mention the specialized type by name.
• A specialization overrides the regular template, and a non template function overrides both.
Here’s how prototypes for swapping type job structures would look for these three forms:
// non template function prototype
void Swap(job &, job &);
// template prototype
template
void Swap(T &, T &);
// explicit specialization for the job type
template <> void Swap
As mentioned previously, if more than one of these prototypes is present, the compiler chooses the non template version over explicit specializations and template versions, and it chooses an explicit specialization over a version generated from a template. For example, in the following code, the first call to Swap() uses the general template, and the second call uses the explicit specialization, based on the job type:
...
template
void Swap(T &, T &);
// explicit specialization for the job type
template <> void Swap
int main()
{
double u, v;
...
Swap(u,v); // use template
job a, b;
...
Swap(a,b); // use void Swap
}
The
template <> void Swap(job &, job &); // simpler form
In case you have to work with an older compiler, we’ll come back to pre-C++ Standard usage soon, but first, let’s see how explicit specializations are supposed to work.
An Example of Explicit Specialization