Deitel & Associates, Inc. Logo

Back to www.deitel.com
digg.png delicious.png blinkit.png furl.png
C++ How to Program, 5/e

ISBN:
0-13-185757-6
© 2005
pages: 1576

Buy the Book!
Amazon logo
InformIT logo

Overloaded functions normally perform similar or identical operations on different types of data. If the operations are identical for each type, they can be expressed more compactly and conveniently using function templates. This tutorial introduces function templates. The tutorial is intended for students and developers who are already familar with C++ functions and function overloading.

Download the code examples for this tutorial.

[Note: This tutorial is an excerpt (Section 14.2) of Chapter 14, Templates, from our textbook C++ How to Program, 5/e. These tutorials may refer to other chapters or sections of the book that are not included here. Permission Information: Deitel, Harvey M. and Paul J., C++ HOW TO PROGRAM, ©2005, pp.751-754. Electronically reproduced by permission of Pearson Education, Inc., Upper Saddle River, New Jersey.]

14.2 Function Templates

Overloaded functions normally perform similar or identical operations on different types of data. If the operations are identical for each type, they can be expressed more compactly and conveniently using function templates. Initially, the programmer writes a single function-template definition. Based on the argument types provided explicitly or inferred from calls to this function, the compiler generates separate object-code functions (i.e., function-template specializations) to handle each function call appropriately. In C, this task can be performed using macros created with the preprocessor directive #define (see Appendix F, Preprocessor). However, macros can have serious side effects and do not enable the compiler to perform type checking. Function templates provide a compact solution, like macros, but enable full type checking.

Error-Prevention Tip 14.1

Function templates, like macros, enable software reuse. Unlike macros, function templates help eliminate many types of errors through the scrutiny of full C++ type checking.

All function-template definitions begin with keyword template followed by a list of template parameters to the function template enclosed in angle brackets (< and >); each template parameter that represents a type must be preceded by either of the interchangeable keywords class or typename, as in

template< typename T >

or

template< class ElementType >

or

template< typename BorderType, typename FillType >

The type template parameters of a function-template definition are used to specify the types of the arguments to the function, to specify the return type of the function and to declare variables within the function. The function definition follows and appears like any other function definition. Note that keywords typename and class used to specify function-template parameters actually mean "any built-in type or user-defined type."

Common Programming Error 14.1

Not placing keyword class or keyword typename before each type template parameter of a function template is a syntax error.

Example: Function Template printArray

Let us examine function template printArray in Fig. 14.1, lines 8–15. Function template printArray declares (line 8) a single template parameter T (T can be any valid identifier) for the type of the array to be printed by function printArray; T is referred to as a type template parameter, or type parameter. You will see nontype template parameters in Section 14.5.

When the compiler detects a printArray function invocation in the client program (e.g., lines 30, 35 and 40), the compiler uses its overload resolution capabilities to find a definition of function printArray that best matches the function call. In this case, the only printArray function with the appropriate number of parameters is the printArray function template (lines 8–15). Consider the function call at line 30. The compiler compares the type of printArray's first argument (int * at line 30) to the printArray function template's first parameter (const T * at line 9) and deduces that replacing the type parameter T with int would make the argument match the parameter. Then, the compiler substitutes int for T throughout the template definition and compiles a printArray specialization that can display an array of int values. In Fig. 14.1, the compiler creates three printArray specializations—one that expects an int array, one that expects a double array and one that expects a char array. For example, the function-template specialization for type int is

void printArray( const int *array, int count )
    {
       for ( int i = 0; i < count; i++ )
          cout << array[ i ] << " ";

       cout << endl;
    } // end function printArray

The name of a template parameter can be declared only once in the template parameter list of a template header but can be used repeatedly in the function's header and body. Template parameter names among function templates need not be unique.

Fig. 14.1 | Function-template specializations of function template printArray.
1   // Fig. 14.1: fig14_01.cpp
2   // Using template functions.
3   #include <iostream>
4   using std::cout;
5   using std::endl;
6
7   // function template printArray definition
8   template< typename T>
9   void printArray( const T *array, int count )
10   {
11      for ( int i = 0; i < count; i++ )
12         cout << array[ i ] << " ";
13
14      cout << endl;
15   } // end function template printArray
16
17   int main()
18   {
19      const int ACOUNT = 5; // size of array a
20      const int BCOUNT = 7; // size of array b
21      const int CCOUNT = 6; // size of array c
22
23      int a[ ACOUNT ] = { 1, 2, 3, 4, 5 };
24      double b[ BCOUNT ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 };
25      char c[ CCOUNT ] = "HELLO"; // 6th position for null
26
27      cout << "Array a contains:" << endl;
28
29      // call integer function-template specialization
30      printArray( a, ACOUNT );
31
32      cout << "Array b contains:" << endl;
33
34      // call double function-template specialization
35      printArray( b, BCOUNT );
36
37      cout << "Array c contains:" << endl;
38
39      // call character function-template specialization
40 printArray( c, CCOUNT );
41      return 0;
42      } // end main

Array a contains:
1 2 3 4 5
Array b contains:
1.1 2.2 3.3 4.4 5.5 6.6 7.7
Array c contains:
H E L L O

Figure 14.1 demonstrates function template printArray (lines 8–15). The program begins by declaring five-element int array a, seven-element double array b and six-element char array c (lines 23–25, respectively). Then, the program outputs each array by calling printArray—once with a first argument a of type int * (line 30), once with a first argument b of type double * (line 35) and once with a first argument c of type char * (line 40). The call in line 30, for example, causes the compiler to infer that T is int and to instantiate a printArray function-template specialization, for which type parameter T is int. The call in line 35 causes the compiler to infer that T is double and to instantiate a second printArray function-template specialization, for which type parameter T is double. The call in line 40 causes the compiler to infer that T is char and to instantiate a third printArray function-template specialization, for which type parameter T is char. It is important to note that if T (line 8) represents a user-defined type (which it does not in Fig. 14.1), there must be an overloaded stream insertion operator for that type; otherwise, the first stream insertion operator in line 12 will not compile.

Common Programming Error 14.2

If a template is invoked with a user-defined type, and if that template uses functions or operators (e.g., ==, +, <=) with objects of that class type, then those functions and operators must be overloaded for the user-defined type. Forgetting to overload such operators causes compilation errors.

In this example, the template mechanism saves the programmer from having to write three separate overloaded functions with prototypes

void printArray( const int *, int );
    void printArray( const double *, int );
    void printArray( const char *, int );

that all use the same code, except for type T (as used in line 9).

Performance Tip 14.1

Although templates offer software-reusability benefits, remember that multiple function-template specializations and class-template specializations are instantiated in a program (at compile time), despite the fact that the template is written only once. These copies can consume considerable memory. This is not normally an issue, though, because the code generated by the template is the same size as the code the programmer would have written to produce the separate overloaded functions.

 
Return to Tutorial Index