Template Functions-Introduction To Programming-Lecture Notes, Study notes of Computer Programming

A program is a precise sequence of steps to solve a particular problem. This course includes basic programming structure like loops, operator, memory allocation, reference, pointers etc. It teaches how to be a good programmer. This lecture handout is about: Template, Functions, Overloading, Explicitly, Specifying, Type, Objects, Data, members, Classes, Swap, integers, Compilers, Features

Typology: Study notes

2011/2012

Uploaded on 08/06/2012

anchal
anchal 🇮🇳

4.6

(9)

95 documents

1 / 13

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
497
Lecture No. 41
Reading Material
Deitel & Deitel - C++ How to Program Chapter. 12
12.2, 12.3
Summary
63) Template Functions
64) Overloading Template Functions
65) Explicitly Specifying the Type in a Template Function
66) Template Functions and Objects
67) Recap
In the previous lecture, we talked about the objects used as data members within
classes. In this case, you will find that there is a lot of code reuse. A completely debug
code is used as building blocks for developing new and more complex classes.
Today’s discussion will mainly focus on a new way of code reuse with an entirely
different style of reuse. This method is called templates.
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 allowing us the reuse of a
certain shape. This is the concept we are going to try and build on here.
docsity.com
pf3
pf4
pf5
pf8
pf9
pfa
pfd

Partial preview of the text

Download Template Functions-Introduction To Programming-Lecture Notes and more Study notes Computer Programming in PDF only on Docsity!

Lecture No. 41

Reading Material

Deitel & Deitel - C++ How to Program Chapter. 12

12.2, 12.

Summary

  1. Template Functions
  2. Overloading Template Functions
  3. Explicitly Specifying the Type in a Template Function
  4. Template Functions and Objects
  5. Recap

In the previous lecture, we talked about the objects used as data members within classes. In this case, you will find that there is a lot of code reuse. A completely debug code is used as building blocks for developing new and more complex classes. Today’s discussion will mainly focus on a new way of code reuse with an entirely different style of reuse. This method is called templates.

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 allowing us the reuse of a certain shape. This is the concept we are going to try and build on here.

docsity.com

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 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.

docsity.com

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 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:

docsity.com

template

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 , 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. 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 #include<iostream.h>

// template function of deciding a larger number template T larger(T x, T y) { T big; if (x > y) big = x; else big = y; return(big); }

docsity.com

else cout<<"First is not larger"<<endl; }

// main function

{ larger(2.1, 9); larger('G', ‘A’); }

The output of the program is: First is not larger First is larger

Overloading Template Functions Let’s take benefit of our knowledge and discuss the things of the next level i.e. function overloading. Under the techniques employed in function overloading, the functions have 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:

// An example of overloaded template functions.

#include<iostream.h>

// template function template void inverse(T &x, T &y) { T temp; temp = x; x = y; y = temp; }

// overloaded inverse fucntion template T inverse(T x) { return (-x);

main()

docsity.com

// the main fucntion

{ 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.

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 might want to use overloaded templates. The same rule of ordinary function overloading applies on template function overloading.

Explicitly Specifying the Type in a Template Function 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 (a); writing 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;

main()

docsity.com

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

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

docsity.com

template 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

public: PhoneCall(const int l, const char b); // constructor PhoneCall PhoneCall::operator-(void); // overloaded operator 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; } // overloaded operator PhoneCall PhoneCall::operator-(void) { PhoneCall::billCode='c'; Return (*this); }

// main function

{ 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

main()

docsity.com

reverse a phone call, how to reverse an int and so on. The idea is combining two very powerful techniques i.e. operator overloading and template 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. 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.

docsity.com