Template In C++

Discussion in 'C++' started by techgeek.in, May 17, 2010.

  1. techgeek.in

    techgeek.in New Member

    Joined:
    Dec 20, 2009
    Messages:
    572
    Likes Received:
    19
    Trophy Points:
    0
    Occupation:
    EOC (exploitation of computers)..i m a Terminator.
    Location:
    Not an alien!! for sure
    Home Page:
    http://www.techgeek.in
    Templates is a concept which enable us to define generic classes and functions and thus provides support for generic programming. Generic programming is an approach where generic types are used as parameters in algorithm so that they work for variety of suitable data types and data structures.

    A template can be considered as a kind of macro. When an object of a specific type is defined for actual use, the template definition for that class is substituted with the required data type. Since a template is defined with a parameter that would be replaced by a specified data type at the time of actual use of the class or function, the template are sometimes called parameterized classes or functions.

    Consider the example of the maximum() function, which returns the maximum of two arguments. All of the following variations make sense:
    • int maximum(int n1,int n2)// return maximum of 2 numbers
    • unsigned maximum(unsigned n1,unsigned n2)
    • double maximum(double n1,double n2)
    • char maximum(char n1,char n2)
    We would like to implement maximum() for all four cases. We could overload maximum() with all the possible versions:
    Code:
    double maximum(double d1, double d2)
    {
    	if (d1 > d2)
    		return d1;
    	return d2;
    }
    
    int maximum(int n1, int n2)
    {
    	if (n1 > n2)
    		return n1;
    	return n2;
    }
    char maximum(char c1, char c2)
    {
    	if (c1 > c2)
    		return c1;
    	return c2;
    }
    // ...repeat for all other numeric types...
    
    This approach works. C++ selects the best match, maximum(int, int), for a reference such as maximum(1, 2). However, creating the same function for each type of variable is a sheer waste of time. The source code for all the maximum(T, T) functions follows the same pattern, where T is one of the numeric types. It would be so convenient if you could write the function once and let C++ supply the type T as needed when the function is used. In fact, C++ lets you do this. These are called template definitions.

    Generalizing a Function into a Template



    A template function enables you to write something that looks like a function but uses one or more type holders that C++ converts into a true type at compile time.

    The following MaxTemplate program defines a template for a generic maximum() function:

    Code:
    // MaxTemplate - create a template max() function that returns the greater of two types
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <typeinfo>
    
    using namespace std;
    
    // simplistic exception class for this example only
    template <class T> 
    T maximum(T t1, T t2)
    {
    	if (t1 > t2)
    	{
    		return t1;
    	}
    	return t2;
    }
    
    int main(int argc, char* pArgs[])
    {
    	// find the maximum of two
    	// here C++ creates maximum(int, int)
    	cout << "The maximum of -1 and 2 is "
    		<< maximum(-1, 2)
    		<< endl;
    
    	// repeat for two doubles;
    	// in this case, we have to provide T explicitly since
    	// the types of the arguments is different
    	cout << "The maximum of 1 and 2.5 is "
    		<< maximum<double>(1, 2.5)
    		<< endl;
    
    	system("PAUSE");
    	return 0;
    }
    
    The keyword template is followed by angle brackets containing one or more type holders known as template parameters, each preceded by the keyword class, a constant, or both. In this case, the definition of maximum<T>(T, T) will call the "unknown type" T. Following the angle brackets is what looks like a normal function definition. In this case, the template function T maximum<T>(T t1, T t2) returns the larger of two objects t1 and t2, each of which is of type T, where T is a class to be defined later.

    A template function is useless until it is converted into a real function. C++ replaces T with an actual type known as a template argument. The main() function first invokes the template definition, passing two arguments of type int. In this case, C++ can instantiate the template providing int as the definition for T.

    Creating a function from a template is called instantiating the template.

    The second call is a problem—no single type can be provided for T in the template definition that matches both the int first argument and double second argument. Here the explicit reference instantiates the function maximum(double, double). C++ promotes the int argument 1 to the double 1.0 before making the call.

    The output from this program appears as follows:

    The maximum of -1 and 2 is 2
    The maximum of 1 and 2.5 is 2.5
    Press any key to continue

    Template Classes



    C++ also allows the programmer to define template classes. A template class follows the same principle of using a conventional class definition with a placeholder for some unknown support classes. For example, the following TemplateVector program creates a vector for any class that the user provides. (A vector is a type of container in which the objects are stored in a row; an array is the classic vector example.)

    Code:
    // TemplateVector - implement a vector that uses a
    //                  template type
    #include <cstdlib>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    // TemplateVector - a simple templatized array
    template <class T>
    class TemplateVector
    {
    public:
    	TemplateVector(int nArraySize)
    	{
    		// store off the number of elements
    		nSize = nArraySize;
    		array = new T[nArraySize];
    		reset();
    	}
    	int size() 
    	{ 
    		return nWriteIndex; 
    	}
    	void reset() 
    	{ 
    		nWriteIndex = 0; nReadIndex = 0; 
    	}
    	void add(const T& object)
    	{
    		if (nWriteIndex < nSize)
    		{
    			array[nWriteIndex++] = object;
    		}
    	}
    	T& get()
    	{
    		return array[nReadIndex++];
    	}
    
    protected:
    	int nSize;
    	int nWriteIndex;
    	int nReadIndex;
    	T* array;
    };
    
    // create and display two vectors:
    //       one of integers and another of names
    
    void intFn();
    void nameFn();
    
    int main(int argc, char* pArgs[])
    {
    	intFn();
    	nameFn();
    
    	system("PAUSE");
    	return 0;
    }
    
    
    // intFn() - manipulate a collection of integers
    void intFn()
    {
    	// create a vector of integers
    	TemplateVector<int> integers(10);
    
    	// add values to the vector
    	cout << "Enter integer values to add to a vector\n"
    		<< "(Enter a negative number to terminate):"
    		<< endl;
    	for(;;)
    	{
    		int n;
    		cin  >> n;
    
    		if (n < 0) { break; }
    		integers.add(n);
    	}
    
    	cout << "\nHere are the numbers you entered:" << endl;
    	for(int i = 0; i < integers.size(); i++)
    	{
    		cout << i << ":" << integers.get() << endl;
    	}
    }
    
    // Names - create and manipulate a vector of names
    class Name
    {
    public:
    	Name() = default;
    	Name(string s) : name(s) {}
    	const string& display() { return name; }
    protected:
    	string name;
    };
    
    void nameFn()
    {
    	// create a vector of Name objects
    	TemplateVector<Name> names(20);
    
    	// add values to the vector
    	cout << "Enter names to add to a second vector\n"
    		<< "(Enter an 'x'
    		for(;;)
    		{
    			string s;
    			cin >> s;
    			if (s == "x" || s == "X") { break; }
    			names.add(Name(s));
    		}
    
    		cout << "\nHere are the names you entered" << endl;
    		for(int i = 0; i < names.size(); i++)
    		{
    			Name& name = names.get();
    			cout << i << ":" << name.display() << endl;
    		}
    }
    
    
    The template class TemplateVector<T> contains an array of objects of class T. The template class presents two member functions: add() and get(). The add() function adds an object of class T into the next empty spot in the array. The corresponding function get() returns the next object in the array. The nWriteIndex and nReadIndex members keep track of the next empty entry and the next entry to read, respectively.

    The intFn() function creates a vector of integers with room for 10 with the declaration:

    TemplateVector<int> integers(10)

    The program reads integer values from the keyboard, saves them off, and then spits the values back out using the functions provided by TemplateVector.

    The second function, nameFn(), creates a vector of Name objects. Again, the function reads in names and then displays them back to the user.

    The TemplateVector handles both int values and Name objects with equal ease.

    A sample output appears as follows (I've bolded input from the keyboard):

    Enter integer values to add to a vector
    (Enter a negative number to terminate):
    5
    10
    15
    -1

    Here are the numbers you entered:
    0:5
    1:10
    2:15
    Enter names to add to a second vector
    (Enter an 'x'
    Chester
    Trude
    Lollie
    Bodie
    x

    Here are the names you entered
    0:Chester
    1:Trude
    2:Lollie
    3:Bodie
    Press any key to continue . . .

    Class Template With Multiple Parameters


    Code:
    # include<iosteam.h>
    using namespace std;
    
    template<class T1, class T2>
    class Test
    {
    	T1 a;
    	T2 b;
    public:
    	Test(T1 x,T2 y)
    	{ 
    		a=x;
    		b=y;
    	}
    	void show()
    	{
    		cout<<a<<" and "<<b<<"\n";
    	}
    };
    
    int main()
    {
    	Test <float,int> test1(1.23,123);
    	Test <int,float> test2(100,'W');
    
    	Test1.show();
    	Test2.show();
    
    	return 0;
    }
    
    The output of the program will be:-
    1.23 and 123
    100 and W

    Overloading Of Template Function



    A template function may be overloaded either by template functions or ordinary fucntions of its name. In such cases, the overloading resolution is accomplished as follows:-

    1. Call an ordinary function that has an exact match.
    2. Call a template function that could be created with an exact match.
    3. Try normal overloading resolution to ordinary functions and call the one that matches.

    An error is generated if no match is found.Note that automatic conversions are applied to arguments on the template functions.

    Code:
    # include<iostream.h>
    # include<string.h>
    using namespace std;
    
    template <class T>
    
    void display(T x)
    {
    	cout<< "Template display";
    }
    
    void display(int x)
    {
    	cout<< "Explicit display: "<<x <<"\n";
    }
    
    int main()
    {
    	display(100);
    	display(12.34);
    	display('C');
    
    	return o;
    }
    

    Other Concepts



    We have seen that a template can have multiple arguments. It is also possible to use non-type argument. That is, in addition to the type argument T, can also use other arguments such as strings, functions names, constant expressions and built-in types. Consider the following examples:-
    Code:
    template<class T, int size>
    class array
    {
        T a[size];
         //.....
         //.....
    };
    
    This template supplies the size of the array sa an argument. this implies that the size of the array is known to the compiler at the compile time itself. The arguments must be specified whenever a template class is created. Example:-

    array<int,10> a1; Array of 10 integers
    array<float,5> a2; Array of 5 floats
    array<char,20> a3; //String of size 20

    Tips For Using Template



    You should remember a few things when using templates. First, no code is generated for a template. (Code is generated after the template is converted into a concrete class or function.) This implies that a .cpp source file is almost never associated with a template class. The entire template class definition, including all the member functions, is contained in the include file so that it can be available for the compiler to expand.

    Second, a template class does not consume memory. Therefore, there is no penalty for creating template classes if they are never instanced. On the other hand, a template class uses memory every time it is instanced. Thus, the code for Array<student> consumes memory even if Array<int> already exists.

    Finally, a template class cannot be compiled and checked for errors until it is converted into a real class. Thus, a program that references the template class Array<T> might compile even though Array<T> contains obvious syntax errors. The errors won't appear until a class such as Array<int> or Array<Student> is created.
     
  2. agrajtech17

    agrajtech17 New Member

    Joined:
    May 21, 2010
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    Occupation:
    shared Hosting
    Location:
    US
    Home Page:
    http://www.cirtexhosting.com/shared.shtml
    is this any similarity between generic pointers and templates,

    what are the most significant use of templates and generic pointers.
    please describe both terms.
     
  3. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice