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.