C++Training 4

66
Introduction to C++ TEMPLATES C++ Training for AT&T MOTOPLYR Team

Transcript of C++Training 4

Page 1: C++Training 4

Introduction to

C++ TEMPLATES

C++ Training for AT&T MOTOPLYR Team

Page 2: C++Training 4

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

Page 3: C++Training 4

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

What is a Template ?

Page 4: C++Training 4

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

Page 5: C++Training 4

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 b) type

c) template 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.

Page 6: C++Training 4

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:

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.

class Key<int> i; class Key<char*> c; class Key<mytype> m;

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

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

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

Page 7: C++Training 4

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

Page 8: C++Training 4

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)

Page 9: C++Training 4

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

Page 10: C++Training 4

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.

Page 11: C++Training 4

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

Page 12: C++Training 4

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.

Page 13: C++Training 4

Template Arguments

There are three kinds of template arguments corresponding to the four types of template parameters:

* type

* non-type

* template

Page 14: C++Training 4

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;

}

Page 15: C++Training 4

Template Non-Type Argumentstemplate <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;

}

Page 16: C++Training 4

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;

}

Page 17: C++Training 4

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.

Page 18: C++Training 4

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.

Page 19: C++Training 4

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;

}

Page 20: C++Training 4

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”

Page 21: C++Training 4

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.

The Keyword “typename” (Contd.)

Page 22: C++Training 4

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.

Function Templates

Page 23: C++Training 4

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: can’t 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*

}

Page 24: C++Training 4

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;

}

Page 25: C++Training 4

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.

Page 26: C++Training 4

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

Page 27: C++Training 4

Overloading Function Templates Rulestemplate<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 non-template 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.

Page 28: C++Training 4

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.

}

Page 29: C++Training 4

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

Page 30: C++Training 4

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

Page 31: C++Training 4

Class Template

friend declaration in class template X

Results of giving friendship

template class <T> class X friend void f1() ; makes f1() a friend of all instantiations of template X. For example, f1() is a friend of

X<int>, X<A>, and X<Y>. 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>.

template class <T> class X friend A::f4() ; makes A::f4() a friend of all instantiations of template X. For example, A::f4() is a friend

of X<int>, X<A>, and X<Y>. 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>.

template class <T> class X

friend class Y; 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>.

Friends And Templates (Contd.)

Page 32: C++Training 4

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.

Page 33: C++Training 4

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

Page 34: C++Training 4

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

Page 35: C++Training 4

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.

Page 36: C++Training 4

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: 6Explicit specialization default argumentsExplicit specialization <double, 10>

Page 37: C++Training 4

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

Page 38: C++Training 4

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<> class X<char>;

X<char>* p;

X<int> i;

// X<char> j;

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

Page 39: C++Training 4

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.

Page 40: C++Training 4

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.

Page 41: C++Training 4

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) { };

Page 42: C++Training 4

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

Page 43: C++Training 4

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.

Page 44: C++Training 4

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

Page 45: C++Training 4

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.

Page 46: C++Training 4

Partial Template SpecializationWhen 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.

Page 47: C++Training 4

Partial Template Specialization SyntaxPartial 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.

Page 48: C++Training 4

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(); }

Page 49: C++Training 4

Partial Template Specialization Syntaxoutput: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.

Page 50: C++Training 4

Partial Template Specialization SyntaxPrimary 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> { };

Page 51: C++Training 4

Partial Template Specialization SyntaxThe 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.

Page 52: C++Training 4

Inheritance In Class TemplatesInheritance works in the template in the same way as that of

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

Page 53: C++Training 4

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>{ //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;

}

Page 54: C++Training 4

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;

}

Page 55: C++Training 4

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;

}

Page 56: C++Training 4

Base-Derived conversions in Templatestemplate <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 calledfunc gets called

This is also an example of smart pointers.

Page 57: C++Training 4

Code Organization with TemplatesWhen 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.

Page 58: C++Training 4

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

Page 59: C++Training 4

Code Organization with TemplatesThe 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) Include the template source file in main source code file.

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

c) Explicit instantiation of the template class in the template source file for some common data types.

Page 60: C++Training 4

Code Organization with Templates (Contd.)

For this we can

a) Include the template source file in main source code file.

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

c) Explicit instantiation of the template class in the template source file for some common data types.

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

Page 61: C++Training 4

Uses of TemplatesIn general C++ templates are used in

a) Template Meta-Programming (Also known as TMP)

b) Implementing Smart Pointers such as auto-ptr.

c) Deciding the policy for a certain task in an algorithm.

d) Standard Template Library (Also known as STL)

Page 62: C++Training 4

Template Meta-ProgrammingTemplate 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

}

Page 63: C++Training 4

References

• “The C++ Programming Language” by Bjarne Stroustrup.

http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp

Page 64: C++Training 4

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

Page 65: C++Training 4

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

Page 66: C++Training 4

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;

}

QUIZ