Template syntax
The template keyword tells the
compiler that the class definition that follows will manipulate one or more
unspecified types. At the time the actual class code is generated from the
template, those types must be specified so that the compiler can substitute
them.
To demonstrate the syntax, here’s a
small example that produces a
bounds-checked
array:
//: C16:Array.cpp
#include "../require.h"
#include <iostream>
using namespace std;
template<class T>
class Array {
enum { size = 100 };
T A[size];
public:
T& operator[](int index) {
require(index >= 0 && index < size,
"Index out of range");
return A[index];
}
};
int main() {
Array<int> ia;
Array<float> fa;
for(int i = 0; i < 20; i++) {
ia[i] = i * i;
fa[i] = float(i) * 1.414;
}
for(int j = 0; j < 20; j++)
cout << j << ": " << ia[j]
<< ", " << fa[j] << endl;
} ///:~
You can see that it looks like a normal
class except for the line
template<class T>
which says that T is the
substitution parameter, and that it represents a type name. Also, you see
T used everywhere in the class where you would normally see the specific
type the container holds.
In Array, elements are inserted
and extracted with the same function: the overloaded operator [ ]
. It
returns a reference, so it can be used on both sides of an equal sign (that is,
as both an lvalue and an
rvalue). Notice that if the index is out of
bounds, the require( ) function is used to
print a message. Since operator[] is an inline, you could
use this approach to guarantee that no array-bounds violations occur, then
remove the require( ) for the shipping code.
In main( ), you can see how
easy it is to create Arrays that hold different types of objects. When
you say
Array<int> ia;
Array<float> fa;
the compiler expands the Array
template (this is called
instantiation) twice, to
create two new generated
classes, which you can think
of as Array_int and Array_float. (Different compilers may decorate
the names in different ways.) These are classes just like the ones you would
have produced if you had performed the substitution by hand, except that the
compiler creates them for you as you define the objects ia and fa.
Also note that duplicate class
definitions
are either avoided by the compiler or merged by the
linker.