Flylib.com

Books Software

 
 
 

Chapter 24. Templates

I l @ ve RuBoard

Chapter 24. Templates

Thou cunning'st pattern of excelling nature.

”Shakespeare, Othello , Act V

I l @ ve RuBoard
I l @ ve RuBoard

24.1 What Is a Template?

Templates are a relatively new addition to C++. They allow you to write generic classes and functions that work for several different data types. The result is that you can write generic code once and then use it over and over again for many different uses. In fact, C++ comes with something called the Standard Template Library (STL), which makes extensive use of templates to provide powerful data-processing tools to the C++ user .

There are some problems with templates, however. Working out the implementation details was very difficult for the people on the C++ Standards Committee. There was a lot of hard fighting involving tanks, motors, and heavy artillery (or the academic equivalent, which is a tartly worded memo). As a result, template implementation details were one of the last items in the C++ Standard to be agreed upon. Later in this chapter, we'll discuss some of the implementation problems with templates.

I l @ ve RuBoard
I l @ ve RuBoard

24.2 Templates: The Hard Way

Suppose we want to define a function max to return the maximum of two items. Actually, we don't want to define just one max function, but a family of functions: one to find the maximum of two int s, one for float s, one for char s, and so on.

We start by defining a parameterized macro to generate the code for the function. This is called the definition stage . The macro looks like this:

#define define_max(type) type max(type d1, type d2) { \
    if (d1 > d2)                                      \
        return (d1);                                  \
    return (d2);                                      \
}

Each line except the last one ends in a backslash ( \ ). A #define macro spans a single line, so the backslash turns our five lines into one. By putting the backslashes in the same column, we can easily tell if we miss one.

This macro generates no code. It merely provides the definition that is used in the next phase to generate the functions we want. This is called the generation phase. The following three statements use the define_max macro to generate three versions of the max function:

define_max(int);
define_max(float);
define_max(char);

Finally, somewhere in the code we use the functions we've just defined. (This is called the use phase , of course.)

int main(  ) {
    float f = max(3.5, 8.7);
    int   i = max(100, 800);
    char ch = max('A', 'Q');

Figure 24-1 shows the source code for the #define style templates and the code generated by them.

Figure 24-1. Code generated by #define style templates
figs/c++2_2401.gif

This method works adequately for simple functions like max . It doesn't work well for larger functions. One drawback to this system is that we must invoke the macro define_max for each data type we want to use. It would be nice if C++ called define_max automatically.

I l @ ve RuBoard
I l @ ve RuBoard

24.3 Templates: The C++ Way

Templates allow you to define a generic function. C++ then uses this template to generate a specific instance of the function as needed. For example, to define the function max as a template, we write:

template<typename kind>
kind max(kind d1, kind d2) {
    if (d1 > d2)                                    
        return (d1);                                
    return (d2);                                    
}

The construct <typename kind> tells C++ that the word kind can be replaced by any type.

This template declaration corresponds to the definition of the parameterized macro. Like the parameterized macro, it generates no code; it merely provides a definition for the next phase.

Now we can use the template much like we used the functions defined by the parameterized macro:

int main(  ) {
    float f = max(3.5, 8.7);
    int   i = max(100, 800);
    char ch = max('A', 'Q');
    int  i2 = max(600, 200);

You may have noticed that we skipped the generation phase. That's because C++ automatically performs the generation for us. In other words, C++ looks at the line:

float f = max(3.5, 8.7);

and sees that it uses the function max (float, float) . It then checks to see whether the code for this function has been generated and generates it if necessary. In other words, everything is automatic. (There are practical limits to what can be done automatically, as you will see in the implementation details section.)

Figure 24-2 shows the code generated by the template implementation of max . From this you can see that the first time max is used for a float it generates the floating-point version of max . Next we use max for int, and the int version of max is created. Note that the last line:

int  i2 = max(600, 200);

does not generate any function. This is because we've already generated the integer version max and don't need to do so again.

Figure 24-2. Template code generation
figs/c++2_2402.gif
I l @ ve RuBoard