14

CHAPTER

Generic Programming
with Templates

C
H
A
P
T
E
R

O
U
T
L
I
N
E
—• 14.1 Introduction
—• 14.2 Need of Template
—• 14.3 Definition of Class Template
—• 14.4 Normal Function Template
—• 14.5 Working of Function Templates
—• 14.6 Class Template with More Parameters
—• 14.7 Function Templates with More Arguments
—• 14.8 Overloading of Template Functions
—• 14.9 Member Function Templates
—• 14.10 Recursion with Template Function
—• 14.11 Class Template with Overloaded Operators
—• 14.12 Class Template Revisited
—• 14.13 Class Templates and Inheritance
—• 14.14 Bubble Sort Using Function Template
—• 14.15 Guidelines for Templates
—• 14.16 Difference Between Templates and Macros
—• 14.17 Linked List with Templates

14.1 INTRODUCTION

Template is one of the most useful characteristics of C++. Few old compilers do not allow template mechanism. Templates are part of ANSI C++ standard. All major compilers support templates in their new versions. Instantiation is the activity of creating particular type using templates. The specific classes are known as instance of the template. The template provides generic programming by defining generic classes. In templates, generic data types are used as arguments and they can handle a variety of data types. A function that works for all C++ data types is called as generic function. Templates help the programmer to declare group of functions or classes. When used with functions they are called function templates. For example, we can create a template for function square( ). It helps us to calculate square of a number of any data type including int, float, long, and double. The templates associated with classes are called as class templates. A template is almost same as macro and it is type-secured. The difference between template and macro is illustrated in Section 14.16.

14.2 NEED OF TEMPLATE

 

Template is a technique that allows using a single function or class to work with different data types. Using template we can create a single function that can process any type of data i.e., the formal arguments of template functions are of template (generic) type. They can accept data of any type such as int, float, long etc. Thus, a single function can be used to accept values of different data types. Figures 14.1 and 14.2 clear the difference between non-template function and template function. Normally, we overload function when we need to handle different data types. This approach increases the program size. The disadvantages are that not only program length is increased but also more local variables are created in the memory. Template safely overcomes all the limitations occurring while overloading function and allows better flexibility to the program. The portability provided by a template mechanism can be extended to classes. The following sections describe use of template in different concepts of C++ programming. Let us understand the process of declaration of a template.

14.3 DEFINITION OF CLASS TEMPLATE

To declare a class of template type, following syntax is used.

Template Declaration

    template class <T>
    class name_of_class 
    {
      // class data member and function
    }

The first statement template class <T> tells the compiler that the following class declaration can use the template data type. T is a variable of template type that can be used in the class to define variable of template type. Both template and class are keywords. The <> (angle bracket) is used to declare variables of template type that can be used inside the class to define variables of template type. One or more variables can be declared separated by comma. Templates cannot be declared inside classes or functions. They must be global and should not be local.

    T k;

Where, k is the variable of type template. Most of the authors use T for defining template; instead of T, we can use any alphabet.

14.1 Write a program to show values of different data types using overloaded constructor.

# include <iostream.h>
# include <conio.h> 
 class data

 {
  public :

  data (char c)
  { cout <<"
"<< " c = "<<c <<" Size in bytes :"<<sizeof(c); } 

  data (int c)
  { cout <<"
"<< " c = "<<c <<" Size in bytes :"<<sizeof(c); }

data (double c)
{ cout <<"
"<< " c = "<<c <<" Size in bytes :"<<sizeof(c);}
};
int main ( ) 
{ clrscr( );
  data h(‘A’);   // passes character type data 
  data i(100);    // passes integer type data
  data j(68.2);   // passes double type data
  return 0;
}   

OUTPUT

c = A Size in bytes :1
c = 100 Size in bytes :2
c = 68.2 Size in bytes :8

Explanation: In the above program, the class data contains three overloaded one argument constructor. The constructor is overloaded for char, int, and double type. In function main( ), three objects h, i and j are created and values passed are of different types. The values passed are char, int, and double type. The compiler invokes different constructors for different data types. Here, in order to manipulate different data types we require overloading the constructor i.e., defining separate function for each non-compatible data type. This approach has the following disadvantages:

(1) Re-defining the functions separately for each data type increases the source code and requires more time.

(2) The program size is increased. Hence, occupies more disk space.

(3) If function contains bug, it should be corrected in every function.

Figure 14.1 shows the working of the program.

images

Fig. 14.1 Working of non-template function

From the above program it is clear that for each data type we need to define separate constructor function. According to data type of argument passed respective constructor is invoked. C++ provides templates to overcome such problems and helps a programmer to develop generic program. The same program is illustrated with template as follows.

14.2 Write a program to show values of different data types using constructor and template.

# include <iostream.h>
# include <conio.h> 
template <class T>

class data 
{
    public :
    data (T c)
    {
    cout <<"
"<< " c = "<<c <<" Size in bytes :"<<sizeof(c);
    }
};

int main( ) 
{
  clrscr( );
  data <char> h(‘A’);

  data <int> i(100); 
  data <float> j(3.12); 
  return 0;
}

OUTPUT

c = A Size in bytes :1
c = 100 Size in bytes :2
c = 3.12 Size in bytes :4

Explanation: In the above program, the constructor contains variable of template T. The template class variable can hold values of any data type. While declaring an object the data type name is given before the object. The variable of template type can accept values of any data type. Thus, the constructor displays the actual values passed. The template variable c can hold values of any data type. The value and space in bytes required by these variables are displayed as the output. The size of data type changes according to the data types used in the program. Figure 14.2 shows the working of the program.

images

Fig. 14.2Working of template function

In the above program, different values are passed using constructor, but for all data types same template function is used.

14.4 NORMAL FUNCTION TEMPLATE

In the last section, we saw how to make a template class. In the same fashion a normal function (not a member function) can also use template arguments. The difference between normal and member function is that normal functions are defined outside the class. They are not members of any class and hence can be invoked directly without using object of dot operator. The member functions are the class members. They can be invoked using object of the class to which they belong. The declaration of template member function is described later in this chapter. In C++ normal functions are commonly used as in C. However, the user who wants to use C++ as better C, can utilize this concept. The declaration of template normal function can be done as follows.

Normal Template Function Declaration

template class <T>

Function_name ( ) 
{
  // code
}

The following program shows practical working of template function.

14.3 Write a program to define normal template function.

# include <iostream.h>
# include <conio.h>

template <class T>

void show ( T x) 
{  cout<<"
 x="<<x ;  }


void main( ) 
{
    clrscr( ); 
    char c=’A’; 
    int i=65; 
    double d=65.254;

    show(c); 
    show(i); 
    show(d);
}

OUTPUT

x=A
x=65
x=65.254

Explanation: Before the body of the function show( ), template argument T is declared. The function show( ) has one argument x of template type. As explained earlier, the template type variable can accept all types of data. Thus, the normal function show( ) can be used to display values of different data types. In function( ), the show( ) function is invoked and char, int and double type of values are passed. The same is displayed in the output.

You are now familiar with utilities of templates. One more point to remember is that when we declare a class template, we can define class data member of template type as well as the member function of the class can also use the template member. For making member function of template type, no separate declaration is needed. The following program explains the above point.

14.4 Write a program to define data members of template type.

# include <iostream.h>
# include <conio.h>

template <class T>

class data
{
  T x;
  public :


  data (T u) { x=u; }


  void show (T y) 
  {
    cout<<" x="<<x; 
    cout<<" y=" <<y<<"
";
  }
};

int main( ) 
{
  clrscr( );
  data  <char> c(‘B’); 
  data  <int> i(100); 
  data  <double> d(48.25);

  c.show(‘A’); 
  i.show(65);
  d.show(68.25); 
  return 0;
}

OUTPUT

x=B y=A
x=100 y=65
x=48.25 y=68.25

Explanation: In this program, before declaration of class data, template <class T> is declared. This declaration allows entire class including member function and data member to use template type argument. We have declared data member x of template type. In addition, the one argument constructor and member function show( ) also have one formal argument of template type.

14.5 Write a program to create square( ) function using template.

# include <iostream.h>
# include <conio.h> 
template <class S>

class sqr 
{
  public :

sqr (S c) 
    {
     cout <<"
"<< " c = "<<c*c;
    }
};

int main( ) 
{
clrscr( );
sqr <int> i(25);
sqr <float> f(15.2);


return 0; 
}

OUTPUT

c = 625
c = 231.039993

Explanation: In the program in the previous page, the class sqr is declared. It contains a constructor with one argument of template type. In main( ) function, the object i indicates int type and f indicates float type. The object i and f invokes the constructor sqr( ) with values 15 and 15.2. The constructor displays the squares of these numbers.

14.5 WORKING OF FUNCTION TEMPLATES

In the last few examples, we learned how to write a function template that works with all data types. After compilation, the compiler cannot guess with which type of data the template function will work. When the template function is called at that moment, from the type of argument passed to the template function, the compiler identifies the data type. Every argument of template type is then replaced with the identified data type and this process is called as instantiating. Thus, according to different data types respective versions of template functions are created. Though the template function is compatible for all data types, it will not save any memory. When template functions are used, four versions of functions are used. They are data type int, char, float, and double. The programmer need not write separate functions for each data type.

14.6 CLASS TEMPLATE WITH MORE PARAMETERS

Like functions, classes can be declared to handle different data types. Such classes are known as class templates. These classes are generic type and member functions of these classes can operate on different data types. The class template may contain one or more parameters of generic data type. The arguments are separated by comma with template declaration. The declaration is as follows:

Template with Multiple Parameters

   template <class T1, class T2>

   class name_of_ class 
  {
      // class declarations and definitions
  }

14.6 Write a program to define a constructor with multiple template variables.

# include <iostream.h>
# include <conio.h>

template <class T1, class T2> 
class data 
{   public :
    data (T1 a, T2 b)
    {     cout <<"
 a = "<<a <<" b = "<<b; }
};
int main( )
{ clrscr( );
  data <int,float> h(2,2.5);
  data <int,char> i(15,’C’);
  data <float,int> j(3.12,50);
  return 0;  }

OUTPUT

a = 2 b = 2.5
a = 15 b = C
a = 3.12 b = 50

Explanation: In the above program, the data constructor has two arguments of generic type. While creating objects, type of arguments is mentioned in the angle bracket. When arguments are more than one they are separated by comma. Consider the statement data< int, float > h (2,2.5). It tells the compiler that the first argument is of integer type and second argument is of float type. When objects are created, constructors are called and values are received by the template arguments. The output of the program is given above.

14.7 FUNCTION TEMPLATES WITH MORE ARGUMENTS

In previous examples, we defined constructors with arguments. In the same fashion, we can also define member functions with generic arguments. The format is given below:

Function Template Declaration

   template <class T>
   return_data_type function_name (parameter of template type) 
     {
       statement1; 
       statement2; 
       statement3;
   }

14.7 Write a program to display the elements of integer and float array using template variables with member function.

# include <iostream.h>
# include <conio.h> 
template <class Tl, class T2>

class data 
{
    public :

void show (T1 a, T2 b)
    {      cout  <<"
a = "<<a <<" b = "<<b;   } 
};

int main( ) 
{
clrscr( ); 
int  i[]={3,5,2,6,8,9,3};
float f[]={3.1,5.8,2.5,6.8,1.2,9.2,4.7};
data <int,float> h;

for (int m=0;m<7;m++)
h.show(i[m],f[m]);
return 0; 
}

OUTPUT

a = 3 b = 3.1
a = 5 b = 5.8
a = 2 b = 2.5
a = 6 b = 6.8
a = 8 b = 1.2
a = 9 b = 9.2
a = 3 b = 4.7

Explanation: In the above program, array elements of integer and float are passed to function show( ). The function show( ) has two arguments of template type i.e., a and b. The show( ) function receives integer and float values and displays them. The output of the program is shown above.

14.8 Write a program to exchange values of two variables. Use template variables as function arguments.

# include <iostream.h>
# include <conio.h>

template <class E>

void exchange(E &a, E &b)
{

  E t=a; 
  a=b; 
  b=t;
}

int main( ) 
{
       clrscr( ); 
       int x=5,y=8;
       cout <<"
 Before exchange "<<"x= "<<x <<" y= "<<y; 
       exchange (x,y);
       cout <<"
 After exchange "<<"x= "<<x <<" y= "<<y; 
       return 0;
}

OUTPUT

Before exchange x= 5 y= 8
After exchange x= 8 y= 5

Explanation: In the above program, exchange( ) is a user-defined function. It has two arguments of template types. In main( ) the function exchange( ) is invoked and two integers are passed. The function exchange( ) receives these values by reference. The values of two variables are exchanged with the help of temporary variable t. In the output the values of variables x and y before and after execution of function exchange( ) are displayed.

14.9 Write a program to define function template with multiple arguments.

# include <iostream.h>
# include <conio.h>

template <class A, class B, class C> 

void show(A c,B i,C f)
{ cout <<"
 c = "<<c <<" i = "<<i <<" f = "<<f; }

int main( ) 
{
  clrscr( );
  show(‘A’,8,50.25); 
  show(7,’B’,70.89);
  return 0;
}

OUTPUT

C = A i = 8 f = 50.25
C = 7 i = B f = 70.89

Explanation: In the above program, templates with A, B, and C classes are declared. The function show( ) has three arguments of type A, B and C respectively. In main( ), the function show( ) is invoked and three values of different data types are passed. The function show( ) displays the values on the screen.

14.8 OVERLOADING OF TEMPLATE FUNCTIONS

A template function also supports overloading mechanism. It can be overloaded by normal function or template function. While invoking these functions an error occurs if no accurate match is met. No implicit conversion is carried out in parameters of template functions. The compiler follows the following rules for choosing appropriate function when program contains overloaded functions.

(1) Searches for accurate match of functions; if found it is invoked.

(2) Searches for a template function through which a function that can be invoked with accurate match can be generated; if found it is invoked.

(3) Attempts normal overloading declaration for the function.

(4) In case no match is found, an error will be reported.

14.10 Write a program to overload a template function.

# include <iostream.h>
# include <conio.h>

template <class A>

void show(A c) 
{
  cout <<"
 Template variable c = "<<c;
}

void show (int f) 
{
  cout <<"
 Integer variable f = "<<f;
}

int main( )
{
clrscr( ); 
show(‘C’); 
show(50); 
show(50.25);

return 0; 
}

OUTPUT

Template variable c = C
Integer variable f = 50
Template variable c = 50.25

Explanation: In the above program, the function show( ) is overloaded. One version contains template arguments and other version contains integer variables. In main( ), the show( ) function is invoked three times with char, int and float and values are passed. The first call executes the template version of function show( ), the second call executes integer version of function show( ) and the third call again invokes the template version of function show( ). Thus, in the above fashion template functions are overloaded.

14.9 MEMBER FUNCTION TEMPLATES

In the previous example, the template function defined were inline i.e., they were defined inside the class. It is also possible to define them outside the class. While defining them outside, the function template should define the function and the template classes are parameterized by the type argument.

14.11 Write a program to define definition of member function template outside the class and invoke the function.

# include <iostream.h>
# include <conio.h>

template <class T>
class data 
{
       public : 
       data (T c);

    };
   template <class T>
   data<T>::data (T c)
       {
       cout <<"
"<< " c = "<<c;
       }
int main( ) 
{
clrscr( );
data <char> h(‘A’);
data <int> i(100);
data <float> j(3.12);
return 0; 
}

OUTPUT

c = A
c = 100
c = 3.12

Explanation: In the above program, the constructor is defined outside the class. When we define outside the class, the member function should be preceded by the template name as given below:

Statements of program 14.11

  template <class T> 
  data<T>::data (T c)

The first line defines template and second line indicates template class type T.

14.10 RECURSION WITH TEMPLATE FUNCTION

Like normal function and member function, the template function also supports recursive execution of itself. The following program illustrates this:

14.12 Write a program to invoke template function recursively.

# include <iostream.h>
# include <conio.h>
# include <process.h>
# include <stdlib.h>
# include <assert.h>

template <class O>

void display (O d) 
{
  cout<<(float) (rand( )%(d*d))<<"
";

  // if (d==1) exit(1); 
  assert(d!=1); 
  display(--d);

}

void main ( ) 
{
  int x=10; 
  clrscr( ),

  display(x);
}

OUTPUT
46
49
38
12
28
17
11
7
0
0

Assertion failed: d!=1, file REC_TEMP.CPP, line 14
Abnormal program termination

Explanation: The template function generates random number and displays it each time when the function display( ) is invoked. The function rand( ) defined in stdlib.h is used. The function calls itself recursively until the value of d becomes 1. The assert( ) statement checks the value of d and terminates the program when condition is satisfied. The assert( ) is defined in assert.h. We can also use if statement followed by exit( ) statement as given in comment statement.

14.11 CLASS TEMPLATE WITH OVERLOADED OPERATORS

The template class permits to declare overloaded operators and member functions. The syntax for creating overloaded operator function is similar to class template members and functions. The following program explains the overloaded operator with template class.

14.13 Write a program to overload + operator for performing addition of two template based class objects.

# include <iostream.h>
# include <conio.h>

template <class T>

class num 
{
  private : 
  T number;

  public:

  num ( )   {   number=0;   }
  void input( ) 
  {
    cout <<"
 Enter a number : ";
    cin>>number;
  }
  num operator +(num);
  void show( )  {   cout <<number;  }
};

template <class T>
num <T> num <T> :: operator + (num <T> c) 
{
  num <T> tmp;
  tmp.number=number+c.number; 
  return (tmp);
}

void main( ) 
{
  clrscr( );
  num <int> n1,n2,n3; 
  n1.input( );

  n2.input( );
  n3=n1+n2;
  cout <<"
	 n3 = ";
  n3.show( );
}

OUTPUT

Enter a number : 8

Enter a number : 4

n3 = 12

Explanation: In the above program, class num is declared with template variable number. The input( ) function is used to read number through the keyboard. The operator +( ) function performs addition of elements of two template objects.

In function main( ), n1, n2 and n3 are three objects of num class. The statement n3=n1+n2 invokes the overloaded operator and addition of two objects is performed. The show( ) function displays the contents of the object.

14.12 CLASS TEMPLATE REVISITED

As explained earlier, the template mechanism can be used safely in every concept of C++ programming such as functions, classes etc. We also learned how to define class templates. Class templates are frequently used for storage of data and can be very powerfully implemented with data structures such as stacks, linked lists etc. So far, our conventional style is to create a stack or linked list that manipulates or stores only a single type of data, for example, int. If we want to store float data type we need to create a new class to handle float data type and so on can be repeated for various data types. However, template mechanism saves our work of re-defining codes by allowing a single template based class or function to work with different data types.

Reusability is the facility provided by inheritance in which a class can be reused. Template also provides reusability. Inheritance allows reuse of previously defined classes whereas using templates, repetitive definition of functions can be avoided and a single function can be used for multiple data types. Hence, the template based function code is reused instead of defining multiple functions.

14.14 Write a program to create template-based stack. Store integer and float in it.

# include <constream.h>
# include <iostream.h>
# include <stdlib.h>

template <class S>

class stack 
{
  S num[5]; 
  int head; 

  public:
  stack ( )  {  head=-1;  }

  void push ( S d) 
  {
    if (head==4) cout <<endl<<"Stack is Full";
    else
    {
       head++;
    num[head]=d; 
    }
} 
    S pop ( ) 
    {
       if (head==-1)   { cout<<"
 Stack is empty";
       return NULL;
  }
  else 
  {
   S d=num[head]; 
   head--; 
   return d;
  } 
  }
  };

void main ( ) 
{
  clrscr( );
  stack <int>s1;
  for (int j=10;j<=60;j+=10)
  s1.push(j);

  for ( j=0;j<=5;j++)

  cout<<endl<<s1.pop( );

  stack <float>s2; 
  for (    j=1;j<=6;j++) 
  s2.push(.1+j );

  for ( j=0;j<=5;j++) 
  cout<<endl<<s2.pop( );
}

OUTPUT

Stack is Full
50
40
30
20
10
Stack is empty
0
Stack is Full
5.1
4.1
3.1
2.1
1.1
Stack is empty
0

Explanation: As shown in the output, the stack class created can store any type of data. In this program, it has stored integer and float type of data. The stack can store five elements. The member function push( ) is used to add elements in the stack and pop( ) function is used to remove elements from the stack. Both functions display messages when stack is either full or empty. When we perform the push( ) operation beyond the limit i.e., pushing element more than stack capacity, the messages displayed will be “Stack is full.” When pop( ) operation is performed beyond the limit i.e., an attempt to erase the element when no element is stored in the stack, the message will be “Stack is empty.” In function main( ), s1 and s2 are template type objects. Using these objects integer and float values are added and displayed respectively. The order in which the elements are pushed in the stack is exactly opposite (reverse) to the order in which they are popped from the stack.

14.13 CLASS TEMPLATES AND INHERITANCE

The template class can also act as base class. When inheritance is applied with template class it helps to compose hierarchical data structure known as container class.

(1) Derive a template class and add new member to it. The base class must be of template type.

(2) Derive a class from non-template class. Add new template type member to derived class.

(3) It is also possible to derive classes from template base class and omit the template features of the derived classes.

As said earlier, the template characteristics of the base class can be omitted by declaring the type while deriving the class. All the template-based variables are substituted with basic data types. The following declaration illustrates derivation of a class using template featured base class.

Template <class TL,…> 
 class XYZ
{
  // Template type data members and member functions
}

  Template <class TL,…> 
  class ABC : public XYZ <TL,…>
{
  // Template type data members and member functions
}

14.15 Write a program to derive a class using template base class.

# include <iostream.h>
# include <constream.h>

template <class T>
class one 
{
  protected: 
  T x,y;

  void display ( ) 
  {
   cout <<x;
  }
};


template <class S>

class two : public one <S> 
{
  S z;
  public :

  two (S a, S b, S c) 
  {
    x=a; 
    y=b; 
    z=c;
  }
  void show ( )
{
cout <<"
 x="<<x <<" y="<< y<<" z="<<z; 
}
};

void main ( ) 
{
  clrscr( );
  two <int> i(2,3,4) ; 

  i.show( );
  two <float> f(1.1,2.2,3.3); 
  f.show( );
}

OUTPUT

x=2 y=3 z=4
x=1.1 y=2.2 z=3.3

Explanation: In the above program the class one is a base class and class two is a template-derived class. Consider the statement given below:

  template <class S>
  class two : public one <S>

Using the above statement derivation is carried out. The base class name is followed by template class name S. The function show( ) is a member of derived class two( ). In function main( ), I and f are objects of class two. The object I is used to pass integer elements and f is used to pass float numbers.

14.14 BUBBLE SORT USING FUNCTION TEMPLATE

In application software, large amount of data is manipulated and sorting techniques are frequently used in such operations. The sorting mechanism helps to view the information in different ways. The template function can also be used in sorting operation. The following program illustrates the use of template function with bubble sorting method.

14.16 Write a program to sort integer and float array elements using bubble sort method.

# include <iostream.h>
# include <conio.h>

template <class S>

void b_sort ( S u[], int k) 
{
  for (int x=0;x<k-1;x++) 
    for (int y=k-1;x<y;y--)

         if (u[y]<u[y-1])  // checks successive numbers
         {
         S p; 
         p=u[y];           //   assigns to temporary variable 
         u[y]=u[y-1];      // exchange of elements
         u[y-1]=p;         // collects from temporary variable
         }
}

void main ( ) 
{
  clrscr( );
  int i[5]={4,3,2,1,-4}; 
  float f[5]={5.3,5.1,5.5,4.5,3.2}; 
  b_sort(i,5);     // call to function
  b_sort(f,5);     // call to function
  int x=0,y=0;
  cout <<"
Integer array elements in ascending order:"; 

  while (x<5) cout <<i[x++] <<" ";   // display contents of integer array 

  cout <<"
Float array elements in ascending order : ";

  while ( y<5) cout <<f[y++] <<" ";  // displays contents of float array
}

OUTPUT

Integer array elements in ascending order:-4 1 2 3 4
Float array elements in ascending order : 3.2 4.5 5.1 5.3 5.5

Explanation: In the above program, b_sort( ) is a function with template and integer arguments. The two for loops are used to obtain two successive numbers of the array. The if statement checks the two successive numbers and if second number is greater than first, they are exchanged using assignment statements. In function main( ), integer and float arrays are declared and initialized. The base addresses (of both arrays) of arrays and number of elements are passed to the function b_sort( ). The function b_sort( ) arranges contents of both the arrays in ascending order. The two while loops display the contents of arrays.

14.15 GUIDELINES FOR TEMPLATES

(1) Templates are applicable when we want to create type secure class that can handle different data types with same member functions.

(2) The template classes can also be involved in inheritance. For example

       template <class T>
       class data : public base<T>

Both data and base are template classes. The class data is derived from template class base.

(3) The template variables also allow us to assign default values. For example,

       template <class T, int x=20>
       Class data 
       {
          t num[x];
       }

(4) The name of the template class is written differently in different situations. While class declaration, it is declared as follows:

       class data { }; 

For member function declaration is as follows:

       void data <T> :: show (T d) { } 

Where, show ( ) is a member function.

Finally, while declaring objects the class name and specific data is specified before object name.

       data <int> i1   // object of class data supports integer values 
       data <float> f1 // object of class data supports float values

(5) All template arguments declared in template argument list should be used for definition of formal arguments . If one of the template arguments is not used , the template will be specious. Consider the example:

       Template < class T>
       T show (void) 
       {
          return x;
       }

In the above example, the template argument T is not used as a parameter and the compiler will report an error.

   template <class T> 
   void show (int y) 
   {    T tmp; }

In the above example, template type argument is not an argument. Possibly the system will crash.

   Template <class T, class S>
   void max ( T & k) 

   {
   S p; 
   }

The template variable S is not used. Therefore, compile time error is generated.

14.16 DIFFERENCE BETWEEN TEMPLATES AND MACROS

(1) Macros are not type safe i.e., a macro defined for integer operation cannot accept float data. They are expanded with no type checking .

(2) It is difficult to find errors in macros.

(3) In case a variable is post-incremented or decremented , the operation is carried out twice.

    # define max(a) a + ++a

    void main ( ) 
     { int a=10, c; 
       c=max(a); 
       cout<<c;
     }

The macro defined in the above macro definition is expanded twice. Hence, it is a serious limitation of macros. The limitation of this program can be removed using templates as shown below:

14.17 Write a program to perform incrimination operation using template.

# include <iostream.h>
# include <constream.h>

template <class T> 
T max(T k)
{
  ++k;
  return k;
}

void main ( ) 
{
  clrscr( ); 
  int a=10, c; 
  c=max(a); 
  cout<<c;
}

OUTPUT
11

Explanation: In the above program, template function max( ) is defined. An integer value is passed to this function. The function max( ) increments the value and returns it.

14.17 LINKED LIST WITH TEMPLATES

The linked lists are one among popular data structures. The following program explains the working of linked list with templates.

14.18 Write a program to create linked list with template class.

# include <iostream.h>
# include <constream.h>

template <class L>

class list 
{
  L t;
  list *next; 
  public :

  list ( L t);

void add_num (list *node) 
{
 node->next=this;

 next=NULL;
}

list *obtainnext( ) { return next;}

L getnum ( ) { return t; }

};

template <class L> list <L>::list (L y) 
{
 t=y; 
 next=0;
}

void main ( ) 
{
 clrscr( );
 list <int> obj(0); 
 list <int> *opt, *last; 
 last=&obj; 
 int j=0;

 while (j<15) 
 {
  opt=new list <int> (j+1); 
  opt->add_num (last);
  last=opt; 
  j++;
 }
 opt=&obj;

 j=0;

 while (j<15) 
 {
  cout<<opt->getnum( ) << " ";
  opt=opt->obtainnext( ); 
  j++;
 }
}

OUTPUT

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

Explanation: In the above program, the class template is declared in the same way as in previous programs. The class list has two arguments. One is of template L type (t) other is of object of the class list (*next). The pointer next points to the next element of the linked list. The add_num( ) function is used to add successive numbers in the linked list. The function obtainnext ( ) returns address of the next element. The function declarator of obtainnext( ) is preceded by symbol ‘*’ because it returns address of the element. In function add_num( ) the pointer next is initialized with zero. If we do not initialize the next with zero it will become wild pointer and may point to any location of the system. Using loop, successive numbers are added and displayed.

SUMMARY

(1) Template is one of the most useful characteristics of C++. It is newly added in C++. Instantiation is the activity of creating particular type using templates. The specific classes are known as instance of the template. The template provides generic programming by defining generic classes. In templates, generic data types are used as arguments and they can handle a variety of data types.

(2) Declaration and definition of every template class starts with the keyword template followed by parameter list.

(3) The class template may contain one or more parameters of generic data type. The arguments are separated by comma with template declaration.

(4) Function template can be defined with one or more parameters.

(5) A template function also supports overloading mechanism. It can be overloaded by normal function or template function.

(6) It is also possible to define member function definition outside the class. While defining them outside, the function template should define the function and the template classes are parameterized by the type argument.

EXERCISES

[A] Answer the following questions.

(1) What are templates?

(2) How can normal function be declared as template function?

(3) How can member function be declared as template function?

(4) How can templates be used for generic programming?

(5) Explain need of templates.

(6) What do you mean by overloading of template function?

(7) Explain class template.

(8) What are the differences between templates and macros?

(9) Explain inheritance with class template.

(10) Explain working of template function.

(11) Describe guidelines for defining templates.

[B] Answer the following by selecting the appropriate option.

(1) templates are suitable for

(a) any data type

(b) basic data type

(c) derived data type

(d) all of the above

(2) template can be declared using the keyword

(a) template

(b) try

(c) class

(d) none of the above

(3) template class is also called as

(a) generic class

(b) container class

(c) virtual class

(d) base class

(4) Function template can accept

(a) only one parameter

(b) only two parameters

(c) any number of parameters

(d) none of the above

(5) The statement temp <void> x where temp is class template

(a) object x can be used to pass integer values

(b) object x can be used to pass float values

(c) cannot be used to pass values but can invoke member function

(d) none of the above

(6) Observe the following program:

        void show (int x) {   cout<<x; }  // normal function

        template <class T> 
        void show (T t) {  cout<<"	"<<t; } // template function

        void main ( ) 
        {
            show(5);
        }

Which function will be invoked first?

(a) normal function

(b) template function

(c) ambiguity is generated

(d) none of the above

(7) Select the correct template definition:

(a) template <class T>

(b) class < template T>

(c) template <T>

(d) template class <T>

(8) Function template are normally defined

(a) in function main( )

(b) globally

(c) anywhere

(d) in a class

(9) Select the true statement from sentences given below related with function template:

(a) The variable names used as formal argument in the template function should be unique.

(b) Every formal variable in the template definition should appear at least once in function signature.

(c) All template definition function must start with the keyword template.

(d) The code in the template varies every time the template function is instantiated.

(10) Which of the following statement declares a function template which does not return any value and contains pointer of type T.

(a) void sort (T *a);

(b) void sort (T *a);

(c) T sort (T *a);

(d) void sort (T a);

[C] Attempt the following programs.

(1) Write a program to define template and display the absolute value for data type int, double, and long.

(2) Write a program to define a template and display the following lines through it:

(a) String “ABCDEFGHIJKL”

(b) Digits 1,2,3,4,5,6,7,8,9

(c) Float 1.2,2.2,3.2,5.4,8.5,2.6,2.4

(3) Write a program to create a template to find the maximum value stored in an array.

(4) Write a program to find reverse of given number using template based function.

(5) Write a program to convert a given decimal number to binary using template function. The user must be able to convert integer and decimal number to hexadecimal.

(6) Write a program to show values of different data types using constructors and templates.

(7) Write a program to define normal template function.

(8) Write a program to pass an object to template function. Display the contents of members of object.

(9) Write a program to display the reverse string using template function.

[D] Find bugs in the following programs.

(1)

    template <class T>

    void show (T t) { cout <<t; }

    class data
    {
       public:
       int x,y,z; data ( ) {   x=1;   y=2;   z=3; }
    };

    void main ( ) 
    { data X; 
      show(X);
    }

(2)

    template <class T>
    class temp 
    {

       T t; 
       public:
       temp ( ) {t=0;}
       void show ( ) { cout <<; } };

    void main ( ) 
    {  temp <void> x; 
       x.show( );  }

(3)

    template <class T> 
    class one 
    {  protected: 
       T x,y;
    };

    class two : public one <T> 
    {   S z; 
    public :
    two (S a, S b, S c)
    {     x=a;     y=b;     z=c;   }
    void show ( )
    { cout <<"
 x="<<x <<" y="<< y<<" z="<<z; } 
    };

    void main ( ) 
    {
      two <float> f(1.1,2.2,3.3); 
      f.show( );
    }

(4)

    template <class T>

    T  main (T x) 
    {
      cout<<x;
    }
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.255.168