1.124J | Fall 2000 | Graduate

Foundations of Software Engineering

Lecture Notes

Templates

Topics

  1. Introduction
  2. Function Templates
  3. Class Templates

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;
}

Course Info

Learning Resource Types
Exams with Solutions
Presentation Assignments
Programming Assignments with Examples
Written Assignments