Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C++ (http://www.go4expert.com/articles/cpp-tutorials/)
-   -   A Beginners Guide to Templates (http://www.go4expert.com/articles/beginners-guide-templates-t2788/)

Sanskruti 31Jan2007 19:18

A Beginners Guide to Templates
 

Introduction



In C++ programs there is use of common data structures like stacks, queues and lists. A program may require a queue of customers and a queue of messages. One could easily implement a queue of customers, then take the existing code and implement a queue of messages. The program grows, and now there is a need for a queue of orders. So we need to make some changes to the queue implementation since the code has been duplicated in many places. Re-inventing source code is not an intelligent approach in an object oriented environment which encourages re-usability. It seems to make more sense to implement a queue that can contain any arbitrary type rather than duplicating code. How does one do that? The answer is to use type parameterization, more commonly referred to as templates.

Templates are very useful when implementing generic constructs like vectors, stacks, lists, queues which can be used with any arbitrary type. C++ templates provide a way to re-use source code as opposed to inheritance and composition which provide a way to re-use object code. Templates are a way of making your classes more abstract by letting you define the behavior of the class without actually knowing what datatype will be handled by the operations of the class. C++ provides two kinds of templates: class templates and function templates.

Function templates



Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one variable type or class without repeating the code for each type. This is achieved through template parameters. A template parameter is a special kind of parameter that can be used to pass a type as parameter. These function templates can use these parameters as if they were regular types.

The format for declaring function templates with type parameters is:
Code: CPP

template <class identifier> function_declaration;
template <typename identifier> function_declaration;

The only difference between both prototypes is the use of either the keyword class or the keyword typename. Its use is indistinct since both expressions have exactly the same meaning and behave exactly the same way.

For example, to create a template function that returns the greater one of two objects we could use:
Code: CPP

template <class XType>
XType GMax (XType a, XType b)
{
 return (a>b?a:b);
}

Here we have created a template function with XType as its template parameter. This template parameter represents a type that has not yet been specified, but that can be used in the template function as if it were a regular type. As you can see, the function template GMax returns the greater of two parameters of this still-undefined type.

To use this function template we use the following format for the function call:

Code: CPP

function_name <type> (parameters);

For example, to call GMax to compare two integer values of type int we can write:

int x,y;
GMax <int> (x,y);

When the compiler encounters this call to a template function, it uses the template to automatically generate a function replacing each appearance of XType by the type passed as the actual template parameter (int in this case) and then calls it. This process is automatically performed by the compiler and is invisible to the programmer.

Here is the entire example:

Code: CPP

// function template
#include <iostream>
using namespace std;
template <class T>
T GMax (T a, T b) {
  T result;
  result = (a>b)? a : b;
  return (result);
}

int main ()
{
  int i=5, j=6, k;
  long l=10, m=5, n;
  k=GMax<int>(i,j);
  n=GMax<long>(l,m);
  cout << k << endl;
  cout << n << endl;
  return 0;
}

In this case we have used T as the template parameter name instead of XType because it is shorter and in fact is a very common template parameter name. But you can use any identifier you like.

In the example above we used the function template GMax() twice. The first time with arguments of type int and the second one with arguments of type long. The compiler has instantiated and then called each time the appropriate version of the function.

As you can see, the type T is used within the GMax() template function even to declare new objects of that type:

T result;

Therefore, result will be an object of the same type as the parameters a and b when the function template is instantiated with a specific type. In this specific case where the generic type T is used as a parameter for GMax the compiler can find out automatically which data type has to instantiate without having to explicitly specify it within angle brackets (like we have done before specifying <int> and <long>).

So we could have written instead:

int i,j;
GMax (i,j);

Sinceboth i and j are of type int, and the compiler can automatically find out that the template parameter can only be int. This implicit method produces exactly the same result:

Code: CPP

// function template II

#include <iostream>
using namespace std;
template <class T>
T GMax (T a, T b) {
  return (a>b?a:b);
}

int main () {
  int i=5, j=6, k;
  long l=10, m=5, n;
  k=GMax(i,j);
  n=GMax(l,m);
  cout << k << endl;
  cout << n << endl;
  return 0;
}

Notice how in this case, we called our function template GMax() without explicitly specifying the type between angle-brackets <>. The compiler automatically determines what type is needed on each call.

Class templates



We also have the possibility to write class templates, so that a class can have members that use template parameters as types. For example:
Code: CPP

template <class T>
class pair {
    T values [2];
  public:
    pair (T first, T second)
    {
      values[0]=first; values[1]=second;
    }
};

The class that we have just defined serves to store two elements of any valid type.

For example, if we wanted to declare an object of this class to store two integer values of type int with the values 115 and 36 we would write:

pair<int> Xobject (115, 36);

this same class would also be used to create an object to store any other type:

pair<float> Xfloats (3.0, 2.18);

The only member function in the previous class template has been defined inline within the class declaration itself. In case that we define a function member outside the declaration of the class template, we must always precede that definition with the template <...> prefix:

Code: CPP

// class templates

#include <iostream>
using namespace std;
template <class T>
class pair {
    T a, b;
  public:
    pair (T first, T second)
      {a=first; b=second;}
    T gmax ();
};

template <class T>
T pair<T>::gmax ()
{
  T retval;
  retval = a>b? a : b;
  return retval;
}

int main () {
  pair <int> Xobject (100, 75);
  cout << Xobject.gmax();
  return 0;
}

Notice the syntax of the definition of member function gmax:

Code: CPP

template <class T>
T pair<T>::gmax ()

Confused by so many T's? There are three T's in this declaration. The first one is the template parameter. The second T refers to the type returned by the function and the third T (the one between angle brackets) is also a requirement. It specifies that this function's template parameter is also the class template parameter.

Template Instantiation



When the compiler generates a class, function or static data members from a template, it is referred to as template instantiation.

A class generated from a class template is called a generated class.
A function generated from a function template is called a generated function.
A static data member generated from a static data member template is called a generated static data member.

The compiler generates a class, function or static data members from a template when it sees an implicit instantiation or an explicit instantiation of the template.

Consider the following sample.

This is an example of implicit instantiation of a function template.

Code: CPP

//max returns the maximum of the two elements
    template <class T>
    T max(T a, T b)
    {
        return a > b ? a : b ;
    }
    void main()
    {
    int I ;
    I = max(10, 15) ; //implicit instantiation of max(int, int)
    char c ;
    c = max('k', 's') ; //implicit instantiation of max(char, char)
    }


In this case the compiler generates functions max(int, int) and max(char, char). The compiler generates definitions using the template function max.

Consider the following sample.

This is an example of explicit instantiation of a function template.

Code: CPP

template <class T>
    void Test(T r_t)
    {
    }

    int main()
    {
    //explicit instantiation of Test(int)
        template void Test<int>(int) ;
        return 0 ;
    }


shabbir 1Feb2007 13:09

Re: A Beginners Guide to Templates
 
Really informative article.

pradeep 7Feb2007 15:57

Re: A Beginners Guide to Templates
 
Could you please brief about the advantages of templates?

Sanskruti 7Feb2007 17:59

Re: A Beginners Guide to Templates
 
Ok soon I will write on this Topic.

ranjithach 9Aug2007 14:53

Re: A Beginners Guide to Templates
 
Hi ,
Pls explain me about Circular queue concept using C++

shabbir 9Aug2007 17:03

Re: A Beginners Guide to Templates
 
Please don't jump into an article with your query but have a separate thread with proper title and you will see better responses.

msdnguide 27May2011 20:22

Re: A Beginners Guide to Templates
 
How to create a template that takes the input as a class that is also templatized? The template should not accept the non templatized classes. They asked this question in Morgan Stanley interview


All times are GMT +5.5. The time now is 03:43.