Template Functions
A template function is used to write a function in which the type of one or more of the arguments is not yet known when we write the code.
The syntax for this is:
template <class T>
function definition;
where T is the name of a class or a struct or perhaps one of the elementary types.
Example: Here is a function to return the larger of two values.
template <class T>
T Larger(const T & X, const T & Y)
{
if (X > Y)
return X;
else
return Y;
}
Notice that this will make sense only if operator > makes sense for type T.
To use this, we simply call Larger with two arguments of the same type, as in:
cout << Larger(c1, c2);
where c1 and c2 are of type char
or
cout << Larger(N1, N2);
where N1 and N2 are of type int.
Example: We could have a template function to add the values in an array of T, returning the sum.
template <class T>
T Sum(T [] A, const int & Size)
{
T Temp = 0;
for (int I = 0; I < Size; I++)
T += A[I];
return Temp;
}
This will make sense only if it makes sense to say Temp = 0 and to use operator += for T.
Template Classes
We can also have template classes.
The syntax for this is:
template <class T>
class definition;
where T is the name of a class or a struct or perhaps one of the elementary types.
Example: Here is a dynamically-sized array class.
template <class T>
class DArray
{
private:
T * A;
int Size;
public:
DArray(); // initialize Size = 0
~DArray(); // delete the array
T operator [](const int & N) const; // for B = A[3];
T & operator [](const int & N); // for A[3] = B;
// (possibly many more)
};
To use this to make a dynamic array of int:
DArray<int> IntList;
To make a dynamic array of float:
DArray<float> FloatList;
These are called instantiations of DArray.
When we write the code for a template class, each method is a template function:
template <class T>
DArray<T>::DArray()
{
...
}
For a template class, the code is included in the header file as well as the class definition. It cannot be compiled until it is instantiated.
Templates with more than one argument
A template class or function can have more than one argument, as in:
template <class T, int Size>
class List
{
private:
T A[Size];
...
};
and we could instantiate it:
List<float, 25> Q;which makes Q an instance of List in which we have an array of 25 floats.
Friends of Template Classes
Sometimes we are inventing a template class and we need to have a friend of that class. In that case, the friend function will have to be a template function. This situation requires a bit of extra care.
For example, suppose we have:
template <class T>
class Gizmo
{
...
};
and we would like for a function called DoIt to be a friend of the Gizmo<T> class. We could add a line such as
friend void DoIt(Gizmo<T> &);
to the class definition, but this will not quite work.
Instead, we need to make it more explicit that this is a template function. We can add the following to the class definition:
template <class S>
friend void DoIt(Gizmo<S>);
and then when we write the code for DoIt, we have:
template <class S>
friend void DoIt(Gizmo<S> Name;)
{
...
}
Here is an example for the DArray class above.
In the class definition, we need to have:
template <class S>
friend ostream & operator<<(ostream &, const Queue< S> &);
and likewise, when we write the code, we will use this heading:
template <class S>
ostream & operator <<(ostream & Os, const Queue<S> & Q)
and then write the code using S instead of T.