Topics
1. Introduction
Templates allow us to write functions and classes that are based on parameterized types. For example, we may wish to write a function or class to run quicksort on (1) an array of _int_s and (2) an array of _float_s. Rather than writing two separate versions, one for _int_s and one for _float_s, we may write a single generic template from which the compiler can generate the int and float versions of quicksort.
2. Function Templates
The following example illustrates how to use function templates.
FunctionTemplates.cpp
#include <iostream.h>
// A function template for creating functions that reverse the order of the elements in an array.
template<typename ItemType>
void reverse(ItemType a[], int N) {
for (int i = 0; i < N/2; i++) {
ItemType tmp = a[i];
a[i] = a[N-1-i];
a[N-1-i] = tmp;
}
}
// A function template, where the type cannot be inferred from the function arguments.
template<typename ItemType>
void print(void *p, int N) {
ItemType *a = (ItemType *)p;
for (int i = 0; i < N; i++)
cout << “Element " << i << " is " << a[i] << endl;
}
// Optional: you are allowed to explicitly instantiate the function templates, if you wish. If you don’t
// do this, the instantiation will occur implicitly as a result of the functions calls below.
template void print<int>(void *, int);
template void print<float>(void *, int);
const int aLength = 5;
const int bLength = 10;
int main() {
int i;
int a[aLength];
float b[bLength];
for (i = 0; i < aLength; i++)
a[i] = i;
for (i = 0; i < bLength; i++)
b[i] = (float)i;
// The compiler will create two versions of reverse(), one to handle ints and one to handle floats.
// In this case, ItemType can be inferred from the first argument.
reverse(a, aLength);
reverse(b, bLength);
// The compiler will create two versions of print(), one to handle ints and one to handle floats.
// In this case, ItemType cannot be inferred from the function arguments. Hence, explicit
// specification of the parameter is required. (VC++ users note: VC++ 6.0 has a bug which
// causes it to use the float version in both cases.)
print<int>((void *)a, aLength);
print<float>((void *)b, bLength);
return 0;
}
3. Class Templates
The following example illustrates how to use class templates.
ArrayClass.h
#include <iostream.h>
// This class template allows us to create array objects of any type and size.
template<typename ItemType, int size>
class ArrayClass {
private:
ItemType array[size];
public:
ArrayClass();
~ArrayClass() {}
void print();
};
// In a class template, all member function definitions should be placed in the header file.
template<typename ItemType, int size>
ArrayClass<ItemType, size>::ArrayClass() {
for (int i = 0; i < size; i++) {
array[i] = (ItemType)(i/2.0); // The chosen default behavior.
}
}
template<typename ItemType, int size>
void ArrayClass<ItemType, size>::print() {
for (int i = 0; i < size; i++) {
cout << array[i] << endl;
}
}
Main.cpp
#include “ArrayClass.h”
int main() {
ArrayClass<int, 5> a;
ArrayClass<float, 10> b;
a.print();
cout << endl;
b.print();
return 0;
}