# Lesson 41

### Template Functions

There are two different types of templates in C++ language i.e.’ function templates and
class templates. Before going ahead, it will be sagacious to know what a template is? You
have used a lot of templates in the childhood. There are small scales being marketed at
the stationary shops having some figures on them like circle, a square, rectangle or a
triangle. We have been using these articles to draw these shapes on the paper. We put the
scale on the paper and draw the lines with the pencil over that figure to get that shape.
These engraved shapes are generally called stencils. But in a way, these are also
templates. We may also take these ‘cut-outs’ as sketches. So a template is a sketch to
draw some shape or figure. While drawing a special design, say of furniture, we develop
a template for this, which is not an actual piece of furniture. We try that its shape should
be like the outline. Later, the cut out prepared out of wood in line with the template, is
actual piece of furniture. We can think of making a triangular template and then drawing
it on a piece of wood and shaping it into a triangle. We can use the same template and put
it on a piece of metal and can cut it into a triangle and so on. In a way, that template is
Page 528
allowing us the reuse of a certain shape. This is the concept we are going to try and build
on here.
Here we are going to discuss the benefits of the function templates. We have been using a
swap
function. We want to interchange two things. You know the technique that we need
a third temp-place holder. If we want to swap two integers i and j, the code will be as
under:
void swap(int &i, int &j)
{
int tmp;
tmp = i;
i = j;
j = tmp;
}
This is a very generic way of interchanging two values. We have written a swap function
to interchange two integers. To interchange two doubles, we have to come up with some
other swap function for doubles and so on. Whenever, a need to use this swapping
technique for different data type arises, we have to write a new function. Can we write
such functions? Yes, we can. These functions can be overloaded. We can have functions
with the same name as long as the types or the number or the arguments are different.
Compiler can detect which function should be used. It will call that function
appropriately. So you can define swap for integers, floats and doubles. There is also no
problem in defining multiple versions of this function with different data types.
Depending on what is required, the compiler will automatically make a call to the correct
function. This is the overloading. The code for every data type looks like:
void swap(SomeDataType &firstThing, SomeDataType &secondThing)
{
SomeDataType tmp;
tmp = firstThing;
firstThing = secondThing;
secondThing = tmp;
}
This is a sort of generic code, we are writing again and again for different data types. It
will be very nice if somehow we can write the code once and let the compiler or language
handle everything else. This way of writing is called templates or function templates. As
seen in the example of a template of a triangle, we will define a generic function. Once it
is defined and determined where it will be called for some specific data type, the
compiler will automatically call that function.
As discussed in the example of overloaded functions, the automatic part is also there.
But we wrote all those functions separately. Here the automatic part is even deeper. In
other words, we write one template function without specifying a data type. If it is to be
Page 529
called for int data type, the compiler will itself write an int version of that function. If it is
to be called for double, the compiler will itself write it. This does not happen at run time,
but at compile time. The compiler will analyze the program and see for which data type,
the template function has been called. According to this, it will get the template and write
a function for that data type.
Now, we will see the idea or technique for defining template function. Here you will
come across some new keywords. First keyword is “template”. These are the recent
addition to the language. Some old compilers may not have these features. However, now
almost all of the compilers implement these features. Another keyword is class that is
quite different than we have been using for defining the classes. This is another use of the
same keyword. Normally, when we define a generic function, it is independent of the
data type. The data type will be defined later in the program on calling this function. The
first line will be as template<generic data type>. This generic data type is written while
using the class key word as template<class variable_name>. So the first line will be as;
template<class T>
We generally use the variable name as T (T evolves from template). However, it is not
something hard and fast. After the variable name, we start writing the function definition.
The function arguments must contain at least one generic data type. Normal function
declaration is:
return_type function_name(argument_list)
return_type
can also be of generic type. There should be at least an argument of generic
type in the argument_list. Let’s take a very simple example. This is the function reverse.
It takes one argument and returns its minus version. The int version of this function is as:
int reverse(int x)
{
return (-x);
}
Similarly its double version will be as:
double reverse(double x)
{
return (-x);
}
Similarly, we can define it for other data types.
Let’s see how can we make a template of this function. The code is as:
template<class T>
Page 530
T reverse(T x)
{
return (-x);
}
In the above function definition, we have used T as generic type. The return type of the
function is T which is accepting an argument of type T. In the body of the function, we
just minus it and return x that is of type T. Now in the main program, if we write it as int i
and then call reverse(i), what will happen? The compiler will automatically detect that i
is an int and reverse is a template function. So, an int version of reverse function is
needed in the program. It uses the template to generate an int version. How does it do
that? It replaces the T with int in the template function. You will get exactly the same
function as we have written before as int reverse(int x). This copy is generated at compile
time. After the compilation, all the code is included in the program. A normal function
call will happen. When we write reverse(i) in the main or some other function, it is not
required to tell that an int version is needed. The compiler will automatically detect the
data type and create a copy of the function of the appropriate data type. This is important
to understand. Similarly if we have double y; and we call the reverse function as
reverse(y)
; the compiler will automatically detect that this program is calling reverse(i)
and reverse(y). Here i is an int and in reverse(y), y is a double. So the compiler will
generate two versions of reverse function, one with int and the other with double. Then it
will be compiled and the program will execute correctly. This is the classic example of
code reuse. We have to pay attention to writing the template. It should be generic in
nature.
For a programmer, there are facilities of the macros and #define which have the
limitations. Macro is a code substitution while #define is a value substitution. Here, in
templates, we write a generic code and the compiler generates its copies of appropriate
types. It is always better than ordinary function overloading. Now let’s take the previous
example of reverse. When we write the function of reverse and give it a value of type
double
, a version of the reverse function for double is created, compiled and used. If we
write the same template in some other program and call it for an integer, it will still work.
It will automatically generate code for int. We should write a template while doing the
same functionality with different data types. The rule for templates is that at least one
argument in the function should be of generic data type. Other wise, it is not a template
function. We write a template class T and use T as a new data type. Being a template data
type, it does not really exist. The compiler will substitute it on its use besides generating
an appropriate code. There are some limitations that should be kept in mind. We cannot
store the declarations and definitions of these functions in different files. In classes, we
have this for certain purposes. In case of a class, we put the declaration of the class and
its basic structure in the header file to facilitate the users to know what the class does
implement. The definition of the class, the actual code of its functions and the
manipulations are provided along with as object code. Here in the template case, the
compiler makes a copy of the source code and converts it to object code. We cannot give
the declaration of the template function in one file and the definition in some other. If we
store these in different files, it will not compile. It does not have real data type and still
Page 531
has parameterized or generic data type in it. So the declaration and definition of a
template function should be in the same file. We will include this file or keep the
template with our main program. When it will be used, the copies of code will be
automatically generated. So it is a slight limitation with templates. In any case, template
class or template functions are for our own use. We do not write template functions as
libraries for other people as it is like giving away our source code.
For template functions, we must have at least one generic argument. There may be more
than one generic arguments. We have to pass it to pieces of data to be swapped. We can
write swap function as:
template<class T>
void swap(T &x, T &y)
{
T tmp;
tmp = x;
x = y;
y = tmp;
}
In the above function, we are passing both arguments of generic type and declared a tmp
variable of generic type. We can also mix generic data types and native data types
including user defined data types. This template version of swap function can be used for
integer, double, float or char. Its copy will be created after writing the swap(a, b) in the
program. If we have int a, b; in the program, int copy of swap function will be generated.
If you have written char a, b; a char copy of swap function will be generated. A copy is
simple substitution of char with T. Just replace T with char in the swap function and
remove the first line i.e. template<class T>, this is the function that the compiler will
generate. Now we have seen examples of one generic and two generic arguments
functions. You can write template functions with more than two generic arguments.
So far, we have been using only one generic data type. However, the things can not be
restricted to only one generic data type. We can use more than one generic data types in
template functions. We can do that by extending the template<class T>. The use of two
generic types can be written as:
template <class T, class U>
We can use any name in place of T and U. Two data types can be mixed here. So we can
write a function that takes an int and float and can multiply these two. We can use T as int
and U as float or whatever is the function requirement. Let’s look at another example of
template function. We want to write a function that takes two arguments of same type and
tells which of the two is greater. The code will be as below:
// A small program shows the use of template function
Page 532
#include<iostream.h>
// template function of deciding a larger number
template<class T>
T larger(T x, T y)
{
T big;
if (x > y)
big = x;
else
big = y;
return(big);
}
// the main function
void main()
{
int i = 7, j = 12;
double x = 4.5, y = 1.3;
cout << "The larger of " << i << " and " << j << " is " << larger(i, j)<< endl;
cout << "The larger of " << x << " and " << y << " is " << larger(x, y)<< endl;
//cout << "The larger of " << x << " and " << y << " is " << larger(i, y)<< endl;
}
The output of the program is:
The larger of 7 and 12 is 12
The larger of 4.5 and 1.3 is 4.5
The function larger is very simple. We have two arguments in it, compared these two
arguments and set the variable bigger. You have noticed that the definition of larger is
not exactly correct. In the if condition, we check that x is greater than y. So in the elsepart
x
can be equal to or lesser than y. Let’s see their use in the main. We declare two
integers i and j and two doubles x and y. Then we use the cout to display the result. The
larger
function will return the bigger argument. When we write larger(i, j), the compiler
will detect it and generate an int version of the larger function. In the next line, we have
used larger(x, y) as x and y are double. Here, the compiler will generate a double version
of the larger function. Now compile the program and it is ready to be executed. The two
versions of larger functions will be executed .We get the larger of two integers and larger
of two doubles. You have noticed that the last line of the code is commented out. In that
line, we are trying to call the larger (i, y). There is a problem that if you uncomment this
line, it will not be compiled. We have only defined one generic class type in the
templatized function i.e. class T. Here we are trying to call it with an int and a double.
The compiler does not know what to do with it. Either it should promote the int to double
and call the double version or demote the double into int and call the int version. But the
Page 533
compiler will not make this decision. It will be a compile time error. We can write
another template function that handles two data types or try to call this function with one
data type. Be careful about these fine points. Template is a nice thing to use but needs to
be used carefully. The compiler may give an error, so you have to correctly use it. Here in
the larger function, we have to provide both arguments of the same data type.
Following is an example of larger function using two different generic types.
// A template function example using two generic types
#include<iostream.h>
// template function
template <class T, class U>
void larger(T val1, U val2)
{
if (val1 > val2)
cout<<"First is larger"<<endl;
else
cout<<"First is not larger"<<endl;
}
// main function
void main()
{
larger(2.1, 9);
larger('G', ‘A’);
}
The output of the program is:
First is not larger
First is larger

Let’s take benefit of our knowledge and discuss the things of the next level i.e. function
the same name but differ either by the number of arguments or the type of the arguments.
Remember that the return type is not a differentiator when you are overloading the
functions. Now if the number or type of the arguments is different and the function name
is same, the compiler will automatically call the correct version. The same rule applies to
the template function. We can write overloaded template functions as long as there is use
of different number or type of arguments.
We have written a templatized swap function. Let’s rename that function as inverse. It
will swap the variables. We have another inverse function that takes one argument and
return the minus of the argument supplied. We have two template functions named
inverse
. Here is the code of the program:
Page 534
// An example of overloaded template functions.
#include<iostream.h>
// template function
template<class T>
void inverse(T &x, T &y)
{
T temp;
temp = x;
x = y;
y = temp;
}
template<class T>
T inverse(T x)
{
return (-x);
}
// the main fucntion
void main()
{
int i = 3, j = 5;
// calling the templatized functions
inverse(i);
inverse(i, j);
cout << “i = ” << i << ", j = " << j << endl;
}
The output of the program is:
i = 5.6, j = -3.4
In the above program, we have overloaded template functions. When we write invers(i),
the compiler will detect the inverse function with one argument and generate its int code.
However, on writing inverse (i, j), it will generate an int version of the inverse function
which takes two parameters. This is not a good example as the function names are
confusing. The function which does swapping should be named as swap while the one
doing negative should be named as negative. There might be good occasions where you

### Explicitly Specifying the Type in a Template Function

Page 535
In the template functions, sometimes we want to see which version of the template
function should be used. Let’s take the example of reverse function. We call that function
for double data type. A function for the double would have been generated and its
negative value will be returned. Suppose we want to pass it a double but return an
integer
. We want to return a negative integer that was a part of the double variable,
passed to the function. We can force the compiler to generate an int version of this
function while not passing it an int. It can take place when we are going to call the
function in the program. We write the data type in the angle brackets between the
function name and argument list. For example, if we have a template reverse function,
which returns -x. In the program, we have double a. As soon as we write reverse(a), the
compiler will generate a double version of reverse function. Now we want that ‘a’ should
be passed to this function while returning an int. The prototype of the function is T
reverse(T x)
. We want that T should be replaced by int. At the same time, we want to pass
it double. To obtain this, we will write as reverse <int> (a); writing <int> forces the
compiler to also generate an integer version of the function. There may be instances
where this technique is useful.
Suppose, we have a template of reverse function that depends on two generic data types.
The function template is as follows:
template <class T, class U>
T reverse (U x)
{
return -x;
}
Now the return type is T while the argument is of type U. In the body of the function, we
return -x and the conversion automatically takes place. In this function template, we are
using two generic types. The return type cannot force anything as it is used later in the
assignment statement. If we have double a in the program, and say reverse(a); What
version will be generated? What will be replaced with T and U? We can force it as
reverse<int>(a);
In that case, it will force T to become int. It will force U to become of
the type a i.e. double. It will take a double number, reverse and convert it into int and
return it. You can explicitly specify it as reverse<int, double> (a); so we have specified
both T and U. We are specifying this to the compiler so that when the compiler generates
the code, it carries out it for these versions. It is like the default argument list. You can
not force the second part only i.e. you can not force U only while missing T. It has to go
left to right. You can do as revere<double, double> (a); or reverse(double, int>(a). The
appropriate versions will be generated. Actually, you can force what type of versions
should be generated in your code. Normally, we do not need to force the template
functions. Normally the template function is used for different data types while
generating appropriate versions by the compiler.
Here is the code of the above-explained program:
// An example of forcing the template functions for some specific data type
Page 536
#include<iostream.h>
template <class T, class U>
T reverse (U x)
{
return (-x);
}
// main function
void main()
{
double amount = -8.8;
// calling the function as double reverse(int)
cout << reverse<double, int>(amount) << endl;
// calling the function as double reverse(double a)
cout << reverse<double>(amount) << endl;
// calling the function as double reverse(double a)
cout << reverse<double, double>(amount) << endl;
// calling the function as int reverse(int a)
cout << reverse<int, int>(amount) << endl;
}
The output of the code is as follows:
8
8.8
8.8
8

### Template Functions and Objects

We have seen the template functions and know that classes also have member functions.
Can we use these templates with the member functions of a class? Yes, we can templatize
member functions. The operations used within template functions should be present in
the public part of the class. Let’s see an example to understand this. Suppose we have
created a class PhoneCall. We have a lengthOfCall data member in the class that tells
about the duration of the call. Another character data member is billCode. The billCode
will tell us that this call is local, domestic or international. Suppose, we browse the bill
and notice a wrong call. What should we do? We will pick up the phone and call the
phone company or go the phone company office to get the bill corrected. How will they
do that? They will verify it with the record and see there is no such call or the duration is
not chargeable. So far, we have been using the reverse function to minus the input
argument. Here we want to reverse the phone call. Suppose, we define that when the
Page 537
billCode
is ‘c’, it means that call has been reversed or cancelled. Can we use this concept
and write a reverse function for this class. Let’s revisit the reverse function template.
template<class T>
T reverse(T x)
{
return (-x);
}
Here T is the generic type that will be replaced with int, float etc. Can we replace T with
the object of the class PhoneCall. How will that work? Let’s replace the T with
PhoneCall
, the code looks like:
PhoneCall reverse(PhoneCall x)
{
return (-x);
}
The declaration line shows that it returns an object of PhoneCall and takes an argument
of type PhoneCall. Inside the body of the function, we are returning -x. What does
PhoneCall
mean? When we are using template functions in the classes, it is necessary to
make sure that whatever usage we are implementing inside the template function, the
class should support it. Here we want to write –PhoneCall. So a minus operator should be
defined for the PhoneCall class. We know how to define operators for classes. Here the
minus operator for PhoneCall will change the billCode to ‘c’ and return the object of type
PhoneCall
. Let’s have a look on the code.
// A simple program to show the usage of the template functions in a class
#include<iostream.h>
// reverse template function
template<class T>
T reverse(T x)
{
return (-x);
}
// definition of a class
class PhoneCall
{
private:
int lengthOfCall; // duration of the call
char billCode; // c for cancelled, d for domestic, i for international, l for local
Page 538
public:
PhoneCall(const int l, const char b); // constructor
int getLengthOfCall(){ return lengthOfCall;}
void showCall(void);
};
PhoneCall::PhoneCall(const int len=0, const char b='l')
{
lengthOfCall = len;
billCode = b;
}
void PhoneCall::showCall(void)
{
cout <<"The duration of the call is " << lengthOfCall << endl;
cout <<"The code of the call is " << billCode << endl;
}
PhoneCall PhoneCall::operator-(void)
{
PhoneCall::billCode='c';
Return (*this);
}
// main function
void main()
{
PhoneCall aCall(10, 'd');
aCall.showCall();
aCall = reverse(aCall);
aCall.showCall();
}
The output of the code is:
The duration of the call is 10
The code of the call is d
The duration of the call is 10
The code of the call is c
We have overloaded the minus operator in the PhoneCall class. We cannot change the
unary or binary nature of operators. The minus operator is lucky due to being unary as
well as binary simultaneously. Here, we have overloaded unary minus operator so, it can
be written as -x. The definition of operators is same as ordinary functions. We can write
whatever is required. Here we are not taking negative of anything but using it in actual
meaning that is reversing a phone call. In the definition of the minus operator, we have
Page 539
changed the billCode to ‘c’ that is cancelled and the object of type PhoneCall is returned.
Now look at the definition of the reverse template function and replace the T with
PhoneCall
. In the body of the function where we have written –x, the minus operator of
the PhoneCall class will be called. Since it is a member operator and the calling object is
available to it. Now let’s look at the main program. We take an object of PhoneCall as
PhoneCall aCall(10, ‘d’);
The object aCall is initialized through the constructor. Now we
display it as aCall.showCall(); that shows the length of the call and bill code. After this,
we say reverse(aCall); The reverse function should not be changing aCall and should
return an object of type PhoneCall. It means that aCall = reverse(aCall); the object
returned is assigned to aCall. Reverse is a template function, so the compiler will
generate a reverse function for PhoneCall. When it will call -x, the member minus
operator of the class PhoneCall will be called. It will change the billCode of that object
and return the object. As we have written aCall = reverse(aCall) so the object returned
from reverse having billCode as ‘c’ will be assigned to aCall. Now while displaying it
using the aCall.showCall(), you will see that the billCode has been changed. So reverse
works.

### Recap

Let’s just recap what we just did in this lecture. We have defined a template function
reverse
. In the template definition, this function returns -x whatever x is passed to it.
After this, we wrote a PhoneCall class and defined its minus operator. Whenever we have
to take minus of the PhoneCall, this operator will be called. This action is based on the
phone call domain and is to change the bill code to ‘c’. So the minus operator returns an
object of type PhoneCall after changing its bill code. Now these two are independent
exercises. The class PhoneCall does not know about the reverse function. It only has
defined its minus operator. On the other hand, the reverse template function has nothing
to do with the PhoneCall class. It is the main program, linking these two things. The
main function declared an object of type PhoneCall and called the reverse function with
that object. When we write the statement aCall = reverse (aCall); the compiler
automatically detects that we have got a situation where reverse template function is
called with the object of type PhoneCall. It needs to generate a copy of this template
function that will work with PhoneCall. When it goes to generate that copy, it encounters
with return(-x). It has to know that a minus operator exists for that class. If we have not
defined the minus operator what will happen. The compiler may give an error that it does
not know what is -PhoneCall. On the other hand, sometimes default substitution takes
place. It may not be what you want to do. You have to be careful and look at the
implications of using a template function with a class and make sure all the operations
within template function should be defined explicitly for the class so that function should
work correctly. Once this is done, you realize that life has become simpler. The same
reverse
function works for this class. Now you can extend the concept and say how to
reverse a car, how to reverse a phone call, how to reverse an int and so on. The idea is
mechanism which provides for writing the code at once. In the normal overloading, the
facility is that we can use the same name again and again. But we have to write the code
each time. Normally, the code is different in these overloaded functions. In this case, we
are saying that we have to write identical code i.e. to reverse something, swap two things.
Page 540
So the code is same only data type is different then we should go and define a template
for that function and thus, template is used again and again. We started with the template
function, used at program level. The use of template with class was also demonstrated.
This combination has some rules. This is that all the operations that template function is
using should be defined in the class. Otherwise, you will have problems.