Activity 14-1 - Introduction to Templates
                        Templates for Functions



Templates allow you to design functions that can be used with arguments of different types.  They also allow us to define classes that are much more general than those you have seen so far.  In order to appreciate the importance of Templates, let's look at one example.

The following function successfully swaps two integer values.

void swap_values(int& variable1, int& variable2)
{
    int temp;

    temp = variable1;
    variable1 = variable2;
    variable2 = temp;
}

This function applies to variables of type int.  But the algorithm is the same for swapping two variables of type char or float.

To swap two variables of type float, we will use:

void swap_values(float& variable1, float& variable2)
{
    float temp;

    temp = variable1;
    variable1 = variable2;
    variable2 = temp;
}

To swap to variables of type char, we will use:
void swap_values(char& variable1, char& variable2)
{
    char temp;

    temp = variable1;
    variable1 = variable2;
    variable2 = temp;
}

This function can even be used to swap the values of two classes.  Suppose we have a class Money, then we can write:

void swap_values(Money& variable1, Money& variable2)
{
    Money temp;

    temp = variable1;
    variable1 = variable2;
    variable2 = temp;
}

As you have noticed except the change in the type, all these functions are almost identical.  How good it would be if we could somehow use one function but change the type as needed.  Well, that is one of the reasons we wish to learn about templates.  We wish to say something like this:

void swap_values(Type_Of_The_Variables& variable1, Type_Of_The_Variables& variable2)
{
   Type_Of_The_Variables temp;

    temp = variable1;
    variable1 = variable2;
    variable2 = temp;
}

Templates for Functions
In order to make a general function for swapping two variables, we use a C++ template for the function swap_values.  This function template allows us to swap the values of any two variables, of any type, so long as these two have the same type.

// Interchanges the values of variable1 and variable2
template<class T>

void swap_values(T& variable1, T& variable2)
{
    T temp;
    temp = variable1;
    variable1 = variable2;
    variable2 = temp;
}

The definition and the function declaration begin with the line:
template<class T>

This is often called the template prefix, and it tells the compiler that the function declaration that follows is a template and that T is a Type parameterIn the context the word class actually means type.   The type parameter T can be replaced with any type.  Within the body of the function definition the type parameter T is used just like any other type.  Following is a program that uses the above template function to swap variables of various types.

// p14_1.cpp Program to demonstrate a function template.
#include <iostream>
using namespace std;

//Interchanges the values of variable1 and variable2.
template<class T>
void swap_values(T& variable1, T& variable2)
{
      T temp;

      temp = variable1;
      variable1 = variable2;
      variable2 = temp;
}

int main()
{
    // swapping two integers
    int integer1 = 1, integer2 = 2;
    cout << "Original integer values are "
         << integer1 << " " << integer2 << endl;
    swap_values(integer1, integer2);
    cout << "Swapped integer values are "
         << integer1 << " " << integer2 << endl;

    // swapping two characters
    char symbol1 = 'A', symbol2 = 'B';
    cout << "Original character values are "
         << symbol1 << " " << symbol2 << endl;
    swap_values(symbol1, symbol2);
    cout << "Swapped character values are "
         << symbol1 << " " << symbol2 << endl;

    return 0;
}

Note that we do not have to have the type as T, and we can use any identifier such a Variable_Type instead of T.

In the following program, function templates are used to sort variables of various types.

Generic Sorting Function
// p14_2.cpp - This is a generic sorting function

#include<iostream>
using namespace std;

template<class T>
void swap_values(T& variable1, T& variable2)
{
      T temp;

      temp = variable1;
      variable1 = variable2;
      variable2 = temp;
}

template<class BaseType>
int index_of_smallest(const BaseType a[], int start_index, int number_used)
{
    BaseType min = a[start_index];
    int index_of_min = start_index;

    for (int index = start_index + 1; index < number_used; index++)
        if (a[index] < min)
        {
            min = a[index];
            index_of_min = index;
            //min is the smallest of a[start_index] through a[index]
        }

    return index_of_min;
}

template<class BaseType>
void sort(BaseType a[], int number_used)
{
int index_of_next_smallest;
for(int index = 0; index < number_used - 1; index++)
   {//Place the correct value in a[index]:
         index_of_next_smallest =
              index_of_smallest(a, index, number_used);
         swap_values(a[index], a[index_of_next_smallest]);
      //a[0] <= a[1] <=...<= a[index] are the smallest of the original array
      //elements. The rest of the elements are in the remaining positions.
   }
}

int main( )
{
    int i;
    int a[10] = {9, 8, 7, 6, 5, 1, 2, 3, 0, 4};
    cout << "Unsorted integers:\n";
        for (i = 0; i < 10; i++)
            cout << a[i] << " ";
    cout << endl;
    sort(a, 10);
    cout << "In sorted order the integers are:\n";
    for (i = 0; i < 10; i++)
        cout << a[i] << " ";
    cout << endl;

    double b[5] = {5.5, 4.4, 1.1, 3.3, 2.2};
    cout << "Unsorted doubles:\n";
    for (i = 0; i < 5; i++)
        cout << b[i] << " ";
    cout << endl;
    sort(b, 5);
    cout << "In sorted order the doubles are:\n";
    for (i = 0; i < 5; i++)
        cout << b[i] << " ";
    cout << endl;

    char c[7] = {'G', 'E', 'N', 'E', 'R', 'I', 'C'};
    cout << "Unsorted characters:\n";
    for (i = 0; i < 7; i++)
        cout << c[i] << " ";
    cout << endl;
    sort(c, 7);
    cout << "In sorted order the characters are:\n";
    for (i = 0; i < 7; i++)
        cout << c[i] << " ";
    cout << endl;

    return 0;
}

Exercise 14.1
In the previous lab, we used recursion in binary search.  In order to carry out a binary search, the set must be sorted.  Use the above program and  the program given below (click here for the complete list) to write a new program that conducts a binary search in:
        1) a set of values of type int,
        2) a set of values of type float,
        3) a set of values of type double, and
        4) a set of values of type char.

Assume that the array may have up to 10 values.

Although, we have only listed four different cases, if the program is written using templates, it can be used for any variable type.

// Recursive program for binary search.
#include <iostream>
using namespace std;

const int ARRAY_SIZE = 10;

void search(const int a[], int first, int last, int key, bool& found, int& location);
int main( )
{
    int a[ARRAY_SIZE];
    const int final_index = ARRAY_SIZE - 1;
    int i;
    for (i = 0; i < 10; i++)
          a[i] = 2*i;

    int key, location;
    bool found;
    cout << "Enter number to be located: ";
    cin >> key;
    search(a, 0, final_index, key, found, location);

    if (found)
        cout << key << " is in index location "
             << location << endl;
    else
        cout << key << " is not in the array." << endl;

    return 0;
}

void search(const int a[], int first, int last, int key, bool& found, int& location)
{
    int mid;
    if (first > last)
    {
        found = false;
    }
    else
    {
        mid = (first + last)/2;

        if (key == a[mid])
        {
            found = true;
            location = mid;
        }
        else if (key < a[mid])
        {
            search(a, first, mid - 1, key, found, location);
        }
        else if (key > a[mid])
        {
            search(a, mid + 1, last, key, found, location);
        }
    }
}