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.