CS210 Lab: Templates


Prelab Questions:

For a review of relevant topics click here.

Highlights of This Lab:

Lab Exercise:


Click the little computer above for a detailed description.
For this excercise you will be asked to implement a function template that will swap two values of any type.

1. What is a Template

A template is a generic function or class which can deal with arbitrary types of data.

Consider the linked list from the 115 lab as pictured below.

There are integer numbers (4, 16, 23, and 55) in this linked list.
What if we wanted to have characters (or any other data type) as data into this structure, as in the below diagram.

We could retype all of the code for the linked list class--changing only the type. Or, we could use a template class--a class which can be seen as a generic class able to handle many types.

1.2 What are Some Advantages of Using Templates?

1.3 There are two kinds of templates:

Let's consider function templates first.

2. Function Templates

Suppose we had the following function which returned the maximum of two integer values passed to it:
#include <iostream>
using namespace std;

int maxi(int a, int b) 
{ 
	return a > b ? a : b ;
}
This condensed code makes use of the ?: ternary operator, also referred to as the conditional operator.
The function above is equivalent to:

int maxi(int a, int b)
{
   if (a > b)
      return a;
   else
      return b;
}

This maxi function works fine for integers, but what if we want to find the maximum of two floating type numbers. We could overload the function and retype the code replacing int with float, or we could use Function Templates.

2.1 Implementing Function Templates

Function templates are implemented like regular functions, except they are prefixed with the keyword template. The following demonstrates in red how we had modified the regular function maxi to make it a function template:

#include <iostream>
using namespace std;

template <typename T> 
T maxi(T a, T b) 
{ 
	return a > b ? a : b ;
}

(To see a side by side comparison of this function template with the regular function, click here)

You can note the following things:

2.2 Using Template Functions

Using function templates is very easy: just call them like regular functions. When the compiler sees an instantiation of the function template, for example: the call maxi(10, 15) in function main, the compiler generates a function maxi(int, int). Similarly the compiler generates definitions for maxi(char, char) and maxi(float, float) in this case.

#include <iostream>
using namespace std ;
//maxi returns the maximum of the two elements
template <typename T>
T maxi(T a, T b)
{
        return a > b ? a : b ;
}
void main()
{
   
        cout << "maxi(10, 15) = " << maxi(10, 15) << endl ;
        cout << "maxi('k', 's') = " << maxi('k', 's') << endl ;
        cout << "maxi(10.1, 15.2) = " << maxi(10.1, 15.2) << endl ;
}

Program Output

maxi(10, 15) = 15
maxi('k', 's') = s
maxi(10.1, 15.2) = 15.2

 

Function Prototypes

As a note, if you need to use a function prototype in your file, preceed it with the template <typename T> specifier. e.g.
template <typename T> T maxi(T & a, T & b);

3. Class Templates

Class templates come in handy when storing data in "containers" (such as linked lists, stacks, and queues). For each container, the type of data may be different, but the methods of manupulating data are the same.

Consider the integer linked list class, which may be represented by this code. The problem with this class is that it handles only integers.

What if we want a linked list with other types (char, float, etc)?

We could create separated classes. For example: OR, we could turn this linked list into a class template and make it more generic.

3.1 Implementing a class template

There are three things to consider when implementing a class template:
(Here, red highlights the syntax specific to class templates)
  1. Creating a class template. The general form is shown below:
    template <typenameTtype >
    class Class_name
    {
    	...
    	...
    }
    
    

  2. Defining member function templates. Use the general form:
    template <typename Ttype>
    return_type Class_name<Ttype>::Function_name
    {
    	...
    	...
    }
    

  3. Creating a specific instance. Use the general form:
    Class_name <type> obj; 
    

3.2 An example of a class template and its use

The following example is meant to get you more familiar with the syntax of class templates. The red font highlights the syntax added for templates.

(To see a side by side comparison of this class template with an ordinary class, click here)

#include <iostream>
using namespace std;

//1. creating a class template 
template <typename T> 
class my_class
{
	T i;
public:
	my_class(T a);
	void show();
};

//2. defining member function for class template
template <typename T> 
my_class<T>::my_class(T a)
{
	i=a;
} 

template <typename T> 
void my_class<T>::show()
{
	cout << "i is: " << i << endl;	
} 


int main()
{
	//3. creating specific instances 
	my_class <int> intobj(10);
	my_class <char> charobj('A');
	intobj.show();
	charobj.show();
	return 0;
}

Program Output

i is: 10
i is: A
In the definitions of intobj and charobj, the data type is enclosed in angle brackets. This data type is the actual parameter (or argument) to the template.

At compile time, the compiler generates (instantiates) two distinct class types and gives its own internal name to each type. You might imagine that the definitions are transformed internally into something like this:

In each of these versions (visualized as my_class_int and my_class_char), the compiler has substituted an actual type (int and char, respectively) for placeholder (T) in the my_class template.

4. Lab Exercise

There are two parts to this lab exercise. In the first part, you create two function templates. In the second part, you create a class template.

Part 1--Function Templates

Part 2--Class Templates