Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

Chapter 27: Tempting C++ Templates 353

This approach works. Now C++ selects the best match, maximum(int, int), for a reference such as maximum(1, 2). However, creating the same function for each type of variable is a gross waste of time.

The source code for all the maximum(T, T) functions follows the same pat­ tern, where T is one of the numeric types. It would be so convenient if you could write the function once and let C++ supply the type T as needed when the function is used. In fact, C++ lets you write the maximum() function in exactly this way and provides an actual type for T as needed.

Generalizing a Function into a Template

A template function enables you to write what looks like a function but that uses one or more type holders that C++ converts into a true type at compile time.

The following MaxTemple program defines a template for a generic maximum() function:

// MaxTemplate - create a template max() function

// that returns the greater of two types #include <cstdio>

#include <cstdlib> #include <iostream>

using namespace std;

// simplistic exception class for this example only template <class T>

T maximum(T t1, T t2)

{

if (t1 > t2)

{

return t1;

}

return t2;

};

int main(int argc, char* pArgs[])

{

//find the maximum of two int’s cout << “The maximum of 1 and 2 is “

<<maximum(1, 2)

<<endl;

//repeat for two doubles

cout << “The maximum of 1.5 and 2.5 is “

354 Part V: Optional Features

<<maximum(1.5, 2.5)

<<endl;

system(“PAUSE”); return 0;

}

The keyword template is followed by angle brackets containing one or more type holders, each preceded by the keyword class, a constant, or both. In this case, the definition of maximum<T>(T, T) will call the “unknown type” T. Following the angle brackets is what looks like a normal function definition. In this case, the template function T maximum<T>(T t1, T t2) returns the larger of two objects t1 and t2, each of which is of type T, where T is a class to be defined later.

A template function is useless until it is converted into a real function. C++ replaces T with an actual type. The main() function implicitly causes C++ to create two versions of maximum() in the MaxTemplate program example.

Creating a function from a template is called instantiating the template.

The first call maximum(1, 2) causes C++ to create a version of the function where T is replaced by int. The second call creates a separate function maximum(double, double). The output from this program appears as follows:

The maximum of 1 and 2 is 2

The maximum of 1.5 and 2.5 is 2.5

Press any key to continue . . .

Be very careful about terminology. For example, I’m a hip, bad bicyclist, which is not the same thing as a bad hip bicyclist. Here’s another example: A template function is not a function. The prototype for a template function is maximum<T>(T, T). The function that this template creates when T is int is the function (not template function) maximum(int, int). Your life will be easier if you remember to keep the terms straight.

Notice that the following won’t work:

double d = max(1, 2.0);

The problem is that the type of the first argument and that of the second don’t match. The type of the arguments must match the template function maximum<T>(T, T) declaration exactly. The example expression would match a template function maximum<T1, T2>(T1, T2). C++ could replace type T1 with int and T2 with double.

You can force the instantiation of a template by providing a prototype decla­ ration. In general, this is safer anyway:

Chapter 27: Tempting C++ Templates 355

float maximum(float, float); // creates an instance of

// maximum<T>(T, T) where T =

float

C++ can’t compile a template function until the template is expanded into a real function. If your template function has compile errors, you probably won’t know it until you instantiate the template function.

Template Classes

C++ also allows the programmer to define template classes. A template class follows the same principle of using a conventional class definition with a placeholder for some unknown support classes. For example, the following TemplateVector program creates a vector for any class that the user provides (a vector is a type of container in which the objects are stored in a row; an array is the classic vector example).

//

TemplateVector - implement a vector that uses a template

//

type

#include <cstdlib> #include <cstdio> #include <iostream> #include <sstream> #include <string> using namespace std;

// TemplateVector - a simple templatized array template <class T>

class TemplateVector

{

public:

TemplateVector(int nArraySize)

{

// store off the number of elements nSize = nArraySize;

array = new T[nArraySize]; reset();

}

int size() { return nWriteIndex; }

void reset() { nWriteIndex = 0; nReadIndex = 0; } void add(T object)

{

if (nWriteIndex < nSize)

{

array[nWriteIndex++] = object;

}

}

T get()

{

356 Part V: Optional Features

return array[nReadIndex++];

}

protected: int nSize;

int nWriteIndex; int nReadIndex; T* array;

};

// exercise two vectors, one of integers and another of names void intFn();

void nameFn();

int main(int argc, char* pArgs[])

{

intFn();

nameFn();

system(“PAUSE”); return 0;

}

// Integers - manipulate a collection of integers void intFn()

{

//create a vector TemplateVector<int> integers(10);

//add values to the vector

cout << “Give me a series integer values to add to a vector\n”

<< “(Enter a negative number to terminate):” << endl;

for(;;)

{

int n; cin >> n;

if (n < 0) { break; } integers.add(n);

}

cout << “\nHere are the numbers you entered” << endl; for(int i = 0; i < integers.size(); i++)

{

cout << i << “:” << integers.get() << endl;

}

}

// Names - create and manipulate a vector of names class Name

{

Chapter 27: Tempting C++ Templates 357

public:

Name(char* n = “”) : name(n) {} string display() { return name; }

protected: string name;

};

void nameFn()

{

//create a vector TemplateVector<Name> names(10);

//add values to the vector cout << “Enter names\n”

<<“(Enter an ‘x’ to quit):” << endl;

for(;;)

{

char buffer[80]; do

{

cin.getline(buffer, 80);

} while(strlen(buffer) == 0); if (stricmp(buffer, “x”) == 0)

{

break;

}

names.add(Name(buffer));

}

cout << “\nHere are the names you entered” << endl; for(int i = 0; i < names.size(); i++)

{

Name name = names.get();

cout << i << “:” << name.display() << endl;

}

}

The template class TemplateVector<T> contains an array of objects of class T. The template class presents two member functions: add() and get(). The add() function adds an object of class T into the next empty spot in the array. The corresponding function get() returns the next object in the array.

The TemplateVector program instantiates this vector class once for simple ints and a second time for the user-defined class Name.

The intFn() function creates a vector of integers with room for 10. The pro­ gram reads integer values from the keyboard, saves them off and then spits the values back out using the functions provided by TemplateVector.

The second function, nameFn(), creates a vector of Name objects. Again, the function reads in names and then displays them back to the user.