Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 66

C++ Training for AT&T MOTOPLYR Team

Introduction to

C++ TEMPLATES

Points of Discussion
What is a Template ? Template Parametrization Template Arguments Class Templates Function Templates Template Instantiation

Template Specialization
Inheritance in Templates Code Organization with Templates General Uses of Template

References
Quiz

What is a Template ?
A template describes a set of related classes or set of related functions in which a list of parameters in the declaration describe how the data type of the members of the set vary.
The compiler generates new classes or functions only when you declare object for template classes or explicitly instantiates a template class for a particular data type or call template functions with template arguments; this process is called template instantiation, C++ provides two kinds of templates :a) Class Template b) Function Template

General Syntax for C++ Templates

C++ supports following syntax for templates.

>--export--<--template--<--template_parameter_list-->--declaration--><

(Optional)

This syntax is valid for both template classes and function.

A template declaration can appear as a namespace scope or class scope declaration.


export keyword is optional. It is not supported by most compilers including g++.

General Syntax for C++ Templates (Contd.)


The template_parameter_list is a comma-separated list of the following kinds of template parameters: a) non-type c) template b) type d) default

The declaration is one of the following:


* a declaration or definition of a function or a class. * a definition of a member function or a member class of a class template.

* a definition of a static data member of a class template.


* a definition of a static data member of a class nested within a class template. * a definition of a member template of a class or class template. A template declaration can appear as a namespace scope or class scope declaration.

General Syntax for C++ Templates (Contd.)


Here the compiler would create three objects. The following table shows the definitions of these three objects if they were written out in source form as regular classes, not as templates:

class Key<int> i;
class Key { int k; int * kptr; int length; public: Key(int); // ... };

class Key<char*> c;
class Key { char* k; char** kptr; int length; public: Key(char*); // ... };

class Key<mytype> m;
class Key { mytype k; mytype* kptr; int length; public: Key(mytype); // ... };

Note that these three classes have different names. The arguments contained within the angle braces are not just the arguments to the class names, but part of the class names themselves. Key<int> and Key<char*> are class names.

Type Template Parameters


The following is the syntax of a type template parameter declaration:
>>-+-class----+--identifier--+---------+----------------------->< '-typename-' '-=--type-'

The identifier is the name of a type. For example


template<class A> Class ABC{ //....

Here A corresponds to the type. To declare an object we will write.


ABC<int> a1; // Note we have passed int as argument while declaring the object.

Non-Type Template Parameters


We can also have the following in the parameter list of the template. * integral or enumeration * pointer to object or pointer to function * reference to object or reference to function * pointer to class member(TBD)

Non-Type Template Parameters


For example, if the templates are defined like this.
template<int a[4]> struct A {}; template<int f(int)> struct B {}; template<int> struct C{}; template<int& b> struct D {D(){cout<<"struct D "<<endl;}}; enum an_enum{X,Y,Z}; template<an_enum> struct E {E(){cout<<"struct E"<<endl;}};

Then their objects can be declared like this.


int g(int a) {return 0;} int i; A<&i> x; B<&g> y; C<100> z; // Here C<i> would be wrong D<i> s; // Here the lvalue is required. E<X> t; // passed enum variable

Non-Type Template Parameters(Contd.)

A template parameter can also be used in the definition of subsequent template parameters.
template<class T,T def_val> class Cont { /* ... */ };

You cannot declare a non-type template parameter as a floating point, class, or void type. For example following is invalid.
template<double x> class Cont { /* ... */ }; // invalid non-type parameter // can't be floating template<int x> class Cont { /* ... */ }; // valid

Non-type template parameters are not lvalues. But when we take reference as a template parameter, the compiler wants lvalue.

Template-Template Parameters
The following is the syntax of a template template parameter declaration:
>>-template--<--template-parameter-list-->--class--+------+--+------------------+->< '-identifier-' ' '-=--id-expression-

Example :
template<template<class A> class B> class C{
B<int> d;// Creating an instance of template B only }; // after instance of template C is created.

template<class E> class F{ E g; }; int main(){

C<F> h; // Notice how are we declaring the object


system("PAUSE"); return 0; }

Please also note that in above case constructor of class F will be called first.

Default-Template Parameters
It follows the same syntax as that for the other types.
//template<class A = int,class Z> class B{ // Error template<class Z,class A = int> class B{ // Valid
A d; }; int main(){ B<float> B1; B<float,char> B2;

system("PAUSE");
return 0; }

If all the template parameters have a default value then that template instance can be declared with empty <> too.

Template Arguments
There are three kinds of template arguments corresponding to the four types of template parameters: * type

* non-type
* template

Template Type Arguments

template<class Z,class A = int> class B{ }; int main(){ B<float,char> B1;// Template Type Arguments B<float> B2;// Template Type Arguments. Second argument would be taken as // default. B<int()> B3;// Again Template Type Argument. Compiler consider int() as a type. return 0; }

Template Non-Type Arguments


template <class type, int size = 100> // size is a non-type parameter class Arr{ type stk[size]; public: Arr(){cout<<"\nArr const\n";} }; template <int s = 100> class ABCD{ const static int j = s; };

int main(){ Arr<float,200> A1;// Template Non-Type Argument '200' Arr<int> A2;// Create an array of integers with size 100 ABCD<50> ABCD1;

ABCD<47-17> ABCD2; // create ABCD template instance of size 30(=47-17)


ABCD<> ABCD3;//Take default value i.e. 100 system(PAUSE); return 0; }

Template-Template Arguments
A template argument for a template-template parameter is the name of a class template.
template<class T, class U> class A { T x; }; template<class U> class B {

short y;
U z; };

int main() { A<B<float>,int> A1; system("PAUSE"); return 0; }

Class Templates
The relationship between a class template and an individual class is like the relationship between a class and an individual object.
An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated. There is a distinction between the terms class template and template class: Class template is a template used to generate template classes. We can have the definition of the template in the header file. Template class is an instance of a class template.

An example of a template class


//template.h. This file contains both declarations and definition of the template. template<class T, int Size> class Stack { T stk[Size]; int top; Public: Stack(); int push(T);

int pop();
}; template<class T,int N> class Stack<T,N>::Stack() { top = 0;

}
// Other functions definition.

Now we can include this header file in our source file and there would be no problem of multiple declaration error.

Operator overloading functions and static members of a template class


template<class T>
class X { public: static T static_var; T operator+(T); }; template<class T> T X<T>::static_var; template<class T> T X<T>::operator+(T arg1) { return arg1; }; int main() { X<char> a; X<int> b; a +'z'; b + 4; }

The Keyword typename


Consider the following class Asia. It contains one nested class India.
class Asia { public: Class India{

int Mohali, Mumbai, Noida;


}; };

Now consider following template.


template<class Z> class Type_Name { Z::India * Sachin; };

This kind of declaration is ambiguous. Any standard compiler will produce an error for this.

The Keyword typename (Contd.)

The tynename keyword tells the compiler that an unknown identifier is a type.
template<class Z> class Type_Name { typename Z::India * Sachin; // compiler will treat Z::India as a type };

typename can also be used in place of the keyword class in template parameter declarations.

Function Templates
A function template defines how a group of functions can be generated. A non-template function is not related to a function template, even though the non-template function may have the same name and parameter profile as those of a specialization generated from a template. A non-template function is never considered to be a specialization of a function template.

Template Argument Deduction


When you call a template function, you may omit any template argument that the compiler can determine or deduce by the usage and context of that template function call. But this is not possible every-time.
template <class T> class vector{ /* ... */ }; template <class T> T* create(); // make a T and return a pointer to it void f() { vector<int > v ; // class, template argument int int* p = create<int>(); // function, template argument int }

One common use of explicit specification is to provide a return type for a template function:
template <class T , class U > T implicit_cast (U u ) { return u ; } void g(int i ) { implicit_cast(i); // error: cant deduce T

implicit_cast<double>(i); // T is double; U is int


implicit_cast<char,double>(i); // T is char; U is double implicit_cast<char*,int>(i); // T is char*; U is int; error: cannot convert int to char* }

Template Argument Deduction


It is not possible every time to deduce the function. For example.
template<class U> int h(){cout<<"func h()"<<endl;}

int main() { h<float>(); // Ok, Will work fine h(); //error can't deduce the function system("PAUSE"); return 0; }

Overloading Function Templates

If you call the name of an overloaded function template, the compiler will try to deduce its template arguments and check its explicitly declared template arguments.
If successful, it will instantiate a function template specialization, then add this specialization to the set of candidate functions used in overload resolution. The compiler proceeds with overload resolution, choosing the most appropriate function from the set of candidate functions.

Non-template functions take precedence over template functions.

Overloading Function Templates(Contd.)


#include <iostream> using namespace std; template<class T> void f(T x, T y) { cout << "Template" << endl;} void f(int w, int z) { cout << "Non-template" << endl; } int main() { f( 1 , 2 );

f('a', 'b'); f( 1 , 'b'); }

Output :
Non-template

Template
Non-template

Argument deduction fails for the function call f(1, 'b') as the compiler does not generate any template function specialization and overload resolution does not take place. The non-template function resolves this function call after using the standard conversion from char to int for the function argument 'b'.

Overloading Function Templates Rules


template<class T> T sqrt(T); template<class T>complex <T> sqrt (complex <T>); double sqrt(double); void f(complex<double>z)

{
sqrt(2);// sqrt<int>(int) sqrt(2.0) ; // sqrt(double) sqrt(z) ; // sqrt<double>(complex<double>) }

we apply the usual function overload resolution rules to these specializations and
all ordinary functions: [1] Find the set of function template specializations that will take part in overload resolution. [2] If two template functions can be called then choose that is more specialized than the other. [3] If a template function argument has been determined by template argument deduction, that argument cannot also have promotions, standard conversions, or user-defined conversions applied. [4] If a non-template function and a specialization are equally good matches, the nontemplate function is preferred. 5] If no match is found, the call is an error. If we end up with two or more equally good matches, the call is ambiguous and is an error.

Practice Code Snippet


template<class T> void f(T) { } template<class T> void f(T*) { }

template<class T> void f(const T*) { }

template<class T> void g(T) { } template<class T> void g(T&) { }

template<class T> void h(T) { } template<class T> void h(T, ...) { }

int main() { const int *p; f(p); // template<class T> void f(const T*) { }

int q; g(q); // Ambiguous. g(T) and g(T&) will considered same while calling.

h(q); // Ambiguous. Ellipses do not affect partial ordering.


}

Friends And Templates


There are four kinds of relationships between template classes and their friend functions : One-to-many: A non-template function may be a friend to all template class instantiations. Many-to-one: All instantiations of a template function may be friends to a regular non-template class. One-to-one: A template function instantiated with one set of template arguments may be a friend to one template class instantiated with the same set of template arguments. This is also the relationship between a regular non-template class and a regular non-template friend function. Many-to-many: All instantiations of a template function may be a friend to all instantiations of the template class.

Friends And Templates (Contd.)


class B{ template<class V> friend int j(); //many-to-one }; template<class S> int g(); template<class T> class A { public: friend int e(); // one-to-many friend int f(T); // one-to-one

friend int g<T>(); // one-to-one


template<class U> friend int h(); //many-to-many };

In case of f(), you may get the following error from compiler.

The friend function declaration "f" will cause an error when the enclosing template class is instantiated with arguments that declare a friend function that does not match an existing definition.
The function declares only one function because it is not a template but the function type depends on one or more template parameters.

These relationships also apply to friend classes.

Friends And Templates (Contd.)

Class Template
template class <T> class X

friend declaration in class template X

Results of giving friendship


makes f1() a friend of all instantiations of template X. For example, f1() is a friend of

friend void f1() ; X<int>, X<A>, and X<Y>.

template class <T> class X template class <T> class X

friend void f2(X<T>&) ;

For a particular type T for example, float, makes f2(X<float>&) a friend of class X<float> only. f2(x<float>&) cannot be a friend of class X<A>. makes A::f4() a friend of all instantiations of template X. For example, A::f4() is a friend

friend A::f4() ;

of X<int>, X<A>, and X<Y>.


template class <T> class X template class <T> class X friend C<T>::f5(X<T>&); For a particular type T for example, float, makes C<float>::f5(X<float>&) a friend of class X<float> only. C<float>::f5(x<float>&) cannot be a friend of class X<A>. makes every member function of class Y a friend of every template class produced from the class template X. template class <T> class X friend class Z<T>; when a template class is instantiated with a particular type T, such as a float, all members of class Z<float> become friends of template class X<float>.

friend class Y;

Template Instantiation
The process of generating a class declaration from a template class and a template argument is often called template instantiation. Similarly, a function is generated (instantiated) from a template function plus a template argument.
template<class L> class Key { //.... } template<class T> void func(){ //... } template class Key<char>;//Explicit instantiation template void func<float>();//Explicit instantiation

void g(){
Key<int> abc;//Implicit instantiation func<int>();//Implicit instantiation }

Note that template instance is created only when compiler hits the template instantiation statement.

Template Specialization
The process of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a template specialization. A primary template is the template that is being specialized.
template<class L> class Key { //.... }; //Primary Template template<> class Key<int> { //.... }; //Specialization. template<> class Key<float> {//... }; //Specialization.

Note that if template instantiation is to be done for specialized instances, then there is no need for the definition of the primary template. Template specialization can be done in two ways. [1] Explicit Specialization [2] Partial Specialization

Explicit Template Specialization


When you instantiate a template with a given set of template arguments the compiler generates a new definition based on those template arguments. We can override this behavior of definition generation. You can instead specify the definition the compiler uses for a given set of template arguments. This is called explicit specialization. We can explicitly specialize any of the following: * Function or class template * Member function of a class template * Static data member of a class template * Member class of a class template * Member function template of a class template * Member class template of a class template

Explicit Template Specialization (Contd.)


The template<> prefix indicates that the following template declaration takes no template parameters.

The declaration_name is the name of a previously declared template.


We can forward-declare an explicit specialization so the declaration_body is optional, at least until the specialization is referenced.

Explicit Template Specialization (Contd.)


template<class T = float, int i = 5> class A { Int value; public: A(); }; template<> class A<> { public: A(); }; template<> class A<double, 10> { public: A(); }; template<class T, int i> A<T, i>::A() : value(i) { cout << "Primary template, " << "non-type argument is " << value << endl; } A<>::A() { cout << "Explicit specialization "<< "default arguments" << endl; } A<double, 10>::A() { cout << "Explicit specialization "<< "<double, 10>" << endl; } int main() A<int,6> x; A<> y; A<double, 10> z; return 0; }

Output :
Primary template non-type argument is: 6 Explicit specialization default arguments Explicit specialization <double, 10>

Explicit Template Specialization (Contd.)


A declaration of a primary template must be in scope at the point of declaration of the explicit specialization. In other words, an explicit specialization declaration must appear after the declaration of the primary template.

For example, the compiler will not allow the following:


template<> class A<int>;//error template<class T> class A;

// or

namespace itaas{ template<class T> class A; }; template<> class A<int>;//error

Explicit Template Specialization (Contd.)


You can use the name of an explicit specialization that has been declared but not defined the same way as an incompletely defined class. The following example demonstrates this:
template<class T> class X { }; template<> X<char>* p; X<int> i; class X<char>;

// X<char> j;

The compiler does not allow the declaration X<char> j because the explicit specialization of X<char> is not defined.

Explicit Template Specialization (Contd.)


A member of an explicitly specialized class is not implicitly instantiated from the member declaration of the primary template. We have to explicitly define members of a class template specialization.
template<class T> class A { public: void f(T); }; template<> class A<int> { public: int g(int); }; int A<int>::g(int arg) { return 0; } int main() { A<int> a; a.g(1234); }

The explicit specialization A<int> contains the member function g(), which the primary template does not.

Explicit Template Specialization (Contd.)


If you explicitly specialize a template, a member template, or the member of a class template, then you must declare this specialization before that specialization is implicitly instantiated. For example, the compiler will not allow the following code:
template<class T> class A { };

void f() { A<int> x; } template<> class A<int> { };

int main() { f(); }

The compiler will not allow the explicit specialization template<> class A<int> { }; because function f() uses this specialization (in the construction of x) before the specialization.

Explicit Template Specialization (Contd.)


In a function template specialization, a template argument is optional if the compiler can deduce it from the type of the function arguments. The explicit specialization template<> void func(X<int>) is equivalent to template<> void func<int>(X<int>). We cannot specify default function arguments in a declaration or a definition for any of the following: * Explicit specialization of a function template * Explicit specialization of a member function template For example, the compiler will not allow the following code:
template<class T> void f(T a) { }; template<> void f<int>(int a = 5) { };

Explicit Template Specialization (Contd.)


Each instantiated class template specialization has its own copy of any static members. You may explicitly specialize static members. The following example demonstrates this:
template<class T> class X { public: static T v; static void f(T); }; template<class T> T X<T>::v = 0; template<class T> void X<T>::f(T arg) { v = arg; } template<> char* X<char*>::v = "Hello"; template<> void X<float>::f(float arg) { v = arg * 2; } int main() { X<char*> a, b; X<float> c; c.f(10); }

This code explicitly specializes the initialization of static data member X::v to point to the string "Hello" for the template argument char*. The function X::f() is explicitly specialized for the template argument float. The static data member v in objects a and b point to the same string, "Hello". The value of c.v is equal to 20 after the call function call c.f(10).

Explicit Template Specialization (Contd.)


We can nest member templates within many enclosing class templates. If you explicitly specialize a template nested within several enclosing class templates, you must prefix the declaration with template<> for every enclosing class template you specialize. You may leave some enclosing class templates unspecialized, however you cannot explicitly specialize a class template unless its enclosing class templates are also explicitly specialized. definition that would output "Template 7" because the enclosing class of class Y (which is class X) is not explicitly specialized. A friend declaration cannot declare an explicit specialization.

Explicit Template Specialization (Contd.)


The following example demonstrates explicit specialization of nested member templates:
template<class T> class X { public: template<class U> class Y { public: template<class V> void f(U,V); void g(U); }; }; template<class T> template<class U> template<class V> void X<T>::Y<U>::f(U, V) { cout << "Template 1" << endl; } template<class T> template<class U> void X<T>::Y<U>::g(U) { cout << "Template 2" << endl; }

template<> template<> void X<int>::Y<int>::g(int) { cout << "Template 3" << endl; }
template<> template<> template<class V> void X<int>::Y<int>::f(int, V) { cout << "Template 4" << endl; } template<> template<> template<> void X<int>::Y<int>::f<int>(int, int) { cout << "Template 5" << endl; } // template<> template<class U> template<class V> // void X<char>::Y<U>::f(U, V) { cout << "Template 6" << endl; } // template<class T> template<> // void X<T>::Y<float>::g(float) { cout << "Template 7" << endl; }

int main() { X<int>::Y<int> a; X<char>::Y<char> b; a.f(1, 2); a.f(3, 'x'); a.g(3); b.f('x', 'y'); b.g('z'); }

The following is the output of the above program: Template 5 Template 4 Template 3 Template 1 Template 2 on

Explicit Template Specialization (Contd.)


The compiler would not allow the template specialization definition that would output "Template 6" because it is attempting to specialize a member (function f()) without specialization its containing class (Y). The compiler would not allow the template specialization definition that would output "Template 7" because the enclosing class of class Y (which is class X) is not explicitly specialized. A friend declaration cannot declare an explicit specialization.

We cannot combine the parameter lists for a template class and its enclosing class.

Partial Template Specialization


When we instantiate a class template, the compiler creates a definition based on the template arguments you have passed. Alternatively, if all those template arguments match those of an explicit specialization, the compiler uses the definition defined by the explicit specialization. A partial specialization is a generalization of explicit specialization. An explicit specialization only has a template argument list. A partial specialization has both a template argument list and a template parameter list. The compiler uses the partial specialization if its template argument list matches a subset of the template arguments of a template instantiation. The compiler will then generate a new definition from the partial specialization with the rest of the unmatched template arguments of the template instantiation. You cannot partially specialize function templates.

Partial Template Specialization Syntax


Partial specialization syntax
>>-template--<template_parameter_list>--declaration_name--------> >-<template_argument_list>--declaration_body------------------><

The declaration_name is a name of a previously declared template.

Note that we can forward-declare a partial specialization so that the declaration_body is optional.

Partial Template Specialization Syntax (Contd.)


template<class T, class U, int I> struct X { void f() { cout << "Primary template" << endl; } }; template<class T, int I> struct X<T, T*, I> { void f() { cout << "Partial specialization 1" << endl; } }; template<class T, class U, int I> struct X<T*, U, I> { void f() { cout << "Partial specialization 2" << endl; } }; template<class T> struct X<int, T*, 10> { void f() { cout << "Partial specialization 3" << endl; } };
template<class T, class U, int I> struct X<T, U*, I> { void f() { cout << "Partial specialization 4" << endl; } }; int main() { X<int, int, 10> a; X<int, int*, 5> b; X<int*, float, 10> c; X<int, char*, 10> d; X<float, int*, 10> e; // X<int, int*, 10> f; a.f(); b.f(); c.f(); d.f(); e.f(); }

Partial Template Specialization Syntax


output:
Primary template Partial specialization 1

Partial specialization 2
Partial specialization 3 Partial specialization 4

The compiler would not allow the declaration X<int, int*, 10> f() because it can match template struct X<T, T*, I>, template struct X<int, T*, 10>, or template struct X<T, U*, I>, and none of these declarations are a better match than the others. Each class template partial specialization is a separate template. We must provide definitions for each member of a class template partial specialization.

Partial Template Specialization Syntax


Primary templates do not have template argument lists; this list is implied in the template parameter list.

Template parameters specified in a primary template but not used in a partial specialization are omitted from the template parameter list of the partial specialization. The order of a partial specialization's argument list is the same as the order of the primary template's implied argument list.
In a template argument list of a partial template parameter, we cannot have an expression that involves non-type arguments unless that expression is only an identifier.
template<int I, int J> class X { }; // Invalid partial specialization template<int I> class X <I * 4, I + 3> { }; // Valid partial specializations template <int I> class X <I, I> { }; template <typename T> class Z <T,45*78-98-78+156-10000> { };

Partial Template Specialization Syntax


The type of a non-type template argument cannot depend on a template parameter of a partial specialization. The compiler will not allow the following partial specialization:

template<class T, T i> class X { };

// Invalid partial specialization template<class T> class X<T, 25> { };

A partial specialization's template argument list cannot be the same as the list implied by the primary template. We cannot have default values in the template parameter list of a partial specialization.

Inheritance In Class Templates


Inheritance works in the template in the same way as that of nontemplate classes. Except that the corresponding template class would be generated just at the time of instantiation. We can have a) Template Base class Template Derived class b) Non-Template Base class Template Derived class c) Template Base class Non-Template Derived class The template/class header for cases (a) and (c) may seem similar. But there is a difference.

Inheritance In Class Templates (Contd.)


template <class T> class A{ int b; public: // Template Base Class

T c;
A(int d,T e):b(d),c(e){} virtual void show(){ cout<<"b is "<<b<<endl;cout<<"c is "<<c<<endl;} }; template<class T> class F: public A<T>{ //Template Derived class int g; public: T h; F(int i,int j,T k):A<T>(i,k),g(j),h(k){} void show(){ cout<<"g is "<<g<<endl;cout<<"h is "<<h<<endl;A<T>::show();}; }; int main() { F<int> f1(2,4,87); f1.show(); system("PAUSE"); return 0; }

Inheritance In Class Templates (Contd.)


class A{ // Non-Template Derived Class int b; public: A(int d):b(d){} virtual void show(){ cout<<"b is "<<b<<endl;} }; template<class T> class F: public A{ // Template Derived Class int g; public: T h; F(int i,int j,T k):A(i),g(j),h(k){} void show(){ cout<<"g is "<<g<<endl;cout<<"h is "<<h<<endl;A::show();}; }; int main() { F<int> f1(2,4,87); f1.show(); system("PAUSE");

return 0;
}

Inheritance In Class Templates (Contd.)


template <class T> class A{ // Template Base Class int b; public: T c; A(int d,T e):b(d),c(e){} virtual void show(){ cout<<"b is "<<b<<endl;cout<<"c is "<<c<<endl;} }; template<class T> class F: public A<T>{ // Non-Template Derived Class. No dependency on template variable T int g; public: F(int i,int j,T k):A<T>(i,k),g(j){} void show(){ cout<<"g is "<<g<<endl;A<T>::show();}; }; int main() { F<int> f1(2,4,87); f1.show(); system("PAUSE"); return 0; }

Base-Derived conversions in Templates


template <class T> class Ptr{ T p; public: Ptr(){} Ptr(T); template <class T2> operator Ptr<T2>(); // Important for compiling }; template <class T> Ptr<T>::Ptr(T ptr) { p = ptr;} template <class T> template <class T2> Ptr<T>::operator Ptr<T2>(){ return static_cast<Ptr<T2> >(p); } class Shape{ }; class Circle : public Shape{ }; class Triangle : public Shape{}; void func(Ptr<Shape*> shape){ cout<<"func gets called"<<endl; } int main() { Ptr<Shape*> ptr1; func(ptr1); Ptr<Circle*> ptr2; func(ptr2); system("PAUSE"); return 0; } Output:

func gets called func gets called

This is also an example of smart pointers.

Code Organization with Templates


When working with normal (non-template) classes, we generally first create a header file containing the definition of a class and a source code file which contains the definition of that class. Then we compile that source file and link it with other translational units.

But in case of templates this is not possible in a normal way.

Code Organization with Templates


// template_itaas.h #ifndef TEMPLATE_ITAAS_H__ #define TEMPLATE_ITAAS_H__ namespace itaas{ template <class T> class itaas_1{ T a; public: itaas_1(T); void show(); }; }; #endif // template_itaas.cpp #include <iostream> #include "template_itaas.h" using namespace std; using namespace itaas; template <class T> itaas_1<T>::itaas_1(T t1){ a = t1;} template <class T> void itaas_1<T>::show(){ cout<<"value of a is "<<a<<endl; } // main.cpp #include <iostream> #include "template_itaas.h" using namespace std; using namespace itaas; int main() { itaas_1<int> i1(10); system("PAUSE"); return EXIT_SUCCESS; }

Code Organization with Templates


The previous example if compiled by g++ main.cpp template_itaas.cpp I./ -o final It will give an error.
[Linker error] undefined reference to `itaas::itaas_1<int>::itaas_1(int)'

As at the time of linking no instance of the template class was instantiated. Template instantiation can be delayed upto the point of linking. But here at the time of linking there was no instance of itaas_1<int>. For this we can a) b) Include the template source file in main source code file. Define all the members of template in the header file.(STL is implemented in the same way. Although, they are the part namespace std but are defined in the header files only.) Explicit instantiation of the template class in the template source file for some common data types.

c)

Code Organization with Templates (Contd.)


For this we can

a)
b)

Include the template source file in main source code file.


Define all the members of template in the header file. (STL is implemented in the same way. Although, they are the part namespace std but are defined in the header files only.) Explicit instantiation of the template class in the template source file for some common data types. We can use keyword export. But this key word is nit supported by many compilers, including g++. Currently, compiler named Comeau is one of the main stream compiler which support export.

c) d)

Uses of Templates
In general C++ templates are used in a) Template Meta-Programming (Also known as TMP)

b)
c) d)

Implementing Smart Pointers such as auto-ptr.


Deciding the policy for a certain task in an algorithm. Standard Template Library (Also known as STL)

Template Meta-Programming
Template metaprogramming is a meta-programming technique in which templates are used by a compiler to generate temporary source code, which is merged by the compiler with the rest of the source code and then compiled. The output of these templates include compile time constants, data structures, and complete functions. The use of templates can be thought of as compile time execution. Compiler act as an interpreter. Its example is
template <int N> struct Factorial { enum { value = N * Factorial<N - 1>::value }; }; template <> struct Factorial<0> { enum { value = 1 }; }; // Factorial<4>::value == 24 // Factorial<0>::value == 1 void foo() { int x = Factorial<4>::value; // == 24 int y = Factorial<0>::value; // == 1 }

References

The C++ Programming Language by Bjarne Stroustrup. http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index .jsp

QUIZ
Ques 1 : What would be the output ?
void f(int a){cout<<"non-template\n";} template <class T> void f(int h){cout<<"template\n";} int main() { // f(); f(457); system("PAUSE"); return 0; }

Ques 2 : How can we hide the definitions of my template code ?

Ques 3 : How can we declare separate template declarations/ definitions for pointer and non-pointer types ?

QUIZ
Ques 4 : If we put the following operator definition in the code, the code still compiles and this operator function gets called.
ostream& operator<<(ostream& os,string str){ //... }

Why is this function does not produce an error as string is a type provided by the namespace std and the operator << is already handled in the namepsacae ? Why don't we get the error of multiple declaration ?

QUIZ
Will the following code compile ?
template<int *a> struct A {A(){cout<<"struct A"<<endl;}}; template<int f(int)> struct B {B(){cout<<"struct B"<<endl;}}; template<int> struct C{C(){cout<<"struct C"<<endl;}};

int g(int a) {return 0;}

int main() { int i; A<&i> x; B<&g> y; C<100> z; // Here C<i> would be wrong system("PAUSE"); return 0; }

You might also like