templates. class templates – why? writing programs we often use abstract data types such as stack,...

21
Templates Templates

Post on 21-Dec-2015

216 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

TemplatesTemplates

Page 2: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Class templates – why?Class templates – why? Writing programs we often use abstract data types such as Writing programs we often use abstract data types such as

stack, queue or tree. Implementations of these types may be stack, queue or tree. Implementations of these types may be almost identical, for example a list of chars and a list of almost identical, for example a list of chars and a list of numbers. They differ only in the type of elements, other numbers. They differ only in the type of elements, other features are the same. features are the same.

A class template is a more general class pattern in which some A class template is a more general class pattern in which some type or class used inside is given as a parameter. A general list type or class used inside is given as a parameter. A general list template may be created first and it may be used to generate template may be created first and it may be used to generate classes like a list of char or a list of figures at need. classes like a list of char or a list of figures at need.

Using templates is better and more comfortable way of Using templates is better and more comfortable way of creating families of types and functions. It is recommended creating families of types and functions. It is recommended over using the preprocessor.over using the preprocessor.

Page 3: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Class templates – declarationClass templates – declaration

template <class T>template <class T> // template whose // template whose argumentargument is type is type TTclass Stackclass Stack // template name is // template name is StackStack{{ T* v; T* v; // bottom of Stack// bottom of Stack T* p; T* p; // top of Stack// top of Stack int size; int size; // capacity of Stack// capacity of Stackpublic:public: Stack (int r) {v = p = new T[size=r];} Stack (int r) {v = p = new T[size=r];} // constructor with argument: // constructor with argument:

// maximal size of stack// maximal size of stack ~Stack () {delete[]v;}~Stack () {delete[]v;} // destructor// destructor void push(T a) {*p++ = a;} void push(T a) {*p++ = a;} // push onto Stack// push onto Stack T pop() {return *--p;} T pop() {return *--p;} // pop from Stack// pop from Stack int getSize() const {return p-v;}int getSize() const {return p-v;} // how many T elements are there now// how many T elements are there now};};

Page 4: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Class templates – declarationClass templates – declaration

template <class T>template <class T> // in template declaration, // in template declaration, // type T is an // type T is an argumentargument// // templatetemplate is a keyword is a keyword

class Stackclass Stack // // Stack Stack is a template nameis a template name

Type (class) T may be used in the declaration as any other Type (class) T may be used in the declaration as any other declared type or class. declared type or class.

Within the scope of declaration of templateWithin the scope of declaration of template Stack Stack the full the full name name Stack<T>Stack<T> is not used; is not used;StackStack is used for template name, constructor and destructor. is used for template name, constructor and destructor.

Outside declaration we refer to template as Outside declaration we refer to template as Stack<T>Stack<T>

Page 5: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Class templates – declaringClass templates – declaring With the template Stack we may declare stacks of With the template Stack we may declare stacks of

various elements, passing the element type as the various elements, passing the element type as the actualactual parameter of the template parameter of the template

The syntax of declaration of a class The syntax of declaration of a class derivedderived from from template:template:

template_name<argument>template_name<argument>

Class – stack of integers:Class – stack of integers:Stack<int>Stack<int>

Class – stack of pointers to figure:Class – stack of pointers to figure:Stack<figure *>Stack<figure *>

Page 6: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

templatestemplates Declaration:Declaration:

Stack<int> numbers (100);Stack<int> numbers (100);

is a declaration of an object named is a declaration of an object named numbersnumbers, , of class of class Stack<int>Stack<int>, , constructor constructor Stack<int>(100)Stack<int>(100) is called. is called.

The name of the class derived from a template may The name of the class derived from a template may be used as any other class name; be used as any other class name; syntax is the only syntax is the only difference.difference.

Page 7: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Stack<figure*> spf(200); Stack<figure*> spf(200); // Stack of pointers to figures// Stack of pointers to figures // of the capacity of 200 ptrs// of the capacity of 200 ptrsStack<Point> sp(400); Stack<Point> sp(400); // Stack of points for 400 elements// Stack of points for 400 elements void f(Stack<complex> &sc) void f(Stack<complex> &sc) // function f, whose argument is// function f, whose argument is // a reference to stack of complex numbers// a reference to stack of complex numbers{{ sc.push(complex(1,2)); sc.push(complex(1,2)); // push a complex onto the stack passed as the // push a complex onto the stack passed as the

argument argument complex z = 2.5 * sc.pop(); complex z = 2.5 * sc.pop(); // pop a number from a Stack, // pop a number from a Stack, // multiply it and store// multiply it and store Stack<int> *p=0;Stack<int> *p=0; // declaration of a pointer // declaration of a pointer // of a Stack of integers// of a Stack of integers p=new Stack<int>(800); p=new Stack<int>(800); // construction of a Stack for 800 ints// construction of a Stack for 800 ints for (int i=0; i<400; i++) for (int i=0; i<400; i++) // 400 times// 400 times {{ p->push(i); p->push(i); // push a number onto a Stack of ints// push a number onto a Stack of ints sp.push(Point(i,i+400)); sp.push(Point(i,i+400)); // push a Point onto a Stack of those// push a Point onto a Stack of those }} delete p; delete p; // destruction of the Stack// destruction of the Stack}}

Page 8: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

ValidationValidation

The compiler checks the validity of template The compiler checks the validity of template only when it is used, so error in the declaration only when it is used, so error in the declaration of a template may not be noticed until it is of a template may not be noticed until it is used to generate a class. used to generate a class. Successful compilation of a declaration of a Successful compilation of a declaration of a

template does not mean that it does not contain template does not mean that it does not contain errors. errors.

It is a good method to create and a specific class It is a good method to create and a specific class first (e.g. first (e.g. Stack_charStack_char) and then to transform it ) and then to transform it into a general template into a general template Stack<T>Stack<T>..

Page 9: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

templatestemplates In the previous version all methods are In the previous version all methods are inline inline — they are defined inside the template. They — they are defined inside the template. They

may also be defined outside:may also be defined outside:

template <class T>template <class T>class Stackclass Stack{{ T* v; T* v; // bottom of Stack// bottom of Stack T* p; T* p; // top of Stack// top of Stack int size; int size; // capacity of Stack// capacity of Stackpublic:public: Stack (int r);Stack (int r); // declaration: constructor with argument// declaration: constructor with argument

~Stack ();~Stack (); void push(T a); void push(T a); // declaration: push onto Stack// declaration: push onto Stack T pop(); T pop(); // declaration: pop from Stack// declaration: pop from Stack int getSize();int getSize(); // how many T elements are there now// how many T elements are there now};};

Page 10: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

templatestemplates If methods are defined outside the declaration of template, the keyword If methods are defined outside the declaration of template, the keyword templatetemplate has to be has to be

used for each:used for each: „„A method of a template is a template of a method”A method of a template is a template of a method”

// definition of e method// definition of e methodtemplate<class T>template<class T>void Stack<T>::push(T a)void Stack<T>::push(T a){{ *p++ = a;*p++ = a;};};

// constructor// constructortemplate<class T>template<class T>Stack<T>::Stack(int r)Stack<T>::Stack(int r){{ v = p = new T[size=r];v = p = new T[size=r];};};

Page 11: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

templates templates Remainder:Remainder: Within the scope of declarationWithin the scope of declaration

template <class T> class Stacktemplate <class T> class Stack the full name the full name Stack<T>Stack<T> is not used; is not used;

StackStack is used for constructor and destructor. is used for constructor and destructor. The code below is wrong:The code below is wrong:

// template<class T>// template<class T>// Stack<T>::// Stack<T>::Stack<T>Stack<T>(int r) (int r) // it is an error,// it is an error,// // // should read: Stack<T>:: // should read: Stack<T>:: StackStack(int r)(int r)//{//{// v = p = new T[size=r];// v = p = new T[size=r];//};//};

Page 12: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Modifying templatesModifying templates A template which is written and used, should not be A template which is written and used, should not be

later modified — the modifications would apply to all later modified — the modifications would apply to all classes derived from this template.classes derived from this template. If we add members, size of all derived objects will grow.If we add members, size of all derived objects will grow. If we change definition of methods, the changes would If we change definition of methods, the changes would

apply to all derived classes. apply to all derived classes.

Therefore, instead of modifying an existing template, Therefore, instead of modifying an existing template, we may create a derived (inheriting) template with we may create a derived (inheriting) template with new features.new features.

Page 13: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Extending of templatesExtending of templates Example: We need a stack of strings with saving and loading from a fileExample: We need a stack of strings with saving and loading from a file

template<class T>template<class T>class Filed_Stack: public Stack<T>class Filed_Stack: public Stack<T>{{ char * file_name;char * file_name;public:public:

/* constructor, parameters size and filename *//* constructor, parameters size and filename */ Stack(int size, char * filename = NULL) Stack(int size, char * filename = NULL) :Stack<T>(size) :Stack<T>(size) // parent construction// parent construction { { // here store the filename// here store the filename }}

void save_Stack();void save_Stack(); void load_Stack();void load_Stack();};};

Page 14: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Special case of templateSpecial case of template If a template would generate invalid code for some specific parameter (type), we If a template would generate invalid code for some specific parameter (type), we

may define a specific case of template for this parameter. E.g: class comparing may define a specific case of template for this parameter. E.g: class comparing objects of some type:objects of some type:

template<class T>template<class T>class comparatorclass comparator // general template// general template{{public:public: static less(T &a, T &b)static less(T &a, T &b) {{ return a<b;return a<b; } } };};

The above is valid for types such as The above is valid for types such as intint or or charchar. For strings . For strings (char *)(char *) not not strings but their addresses would be compared, which is not proper.strings but their addresses would be compared, which is not proper.

Page 15: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Special case of templateSpecial case of template For strings For strings (char *)(char *) not strings but their addresses would be compared, which is not strings but their addresses would be compared, which is

not proper. Therefore we create a special case of template, which will be used only not proper. Therefore we create a special case of template, which will be used only for strings, instead of the version generated from the general template:for strings, instead of the version generated from the general template:

class comparator<char *>class comparator<char *> // special case of template for strings// special case of template for strings{{public:public: static less(const char * a, const char * b)static less(const char * a, const char * b) {{ return strcmp(a, b)<0;return strcmp(a, b)<0; } } };};

The compiler will use the special case if it is visible in the point where it may be The compiler will use the special case if it is visible in the point where it may be used (it should be declared above). Otherwise the general template will be used (it should be declared above). Otherwise the general template will be expanded.expanded.

Page 16: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Template argumentsTemplate arguments A template may have many arguments. They can be classes, but also functions and A template may have many arguments. They can be classes, but also functions and

constant expressionsconstant expressions Example: a buffer template whose size is a parameter:Example: a buffer template whose size is a parameter:

template<class T, int size>template<class T, int size>class bufferclass buffer{{ T w[size];T w[size]; // ...// ...}}

How to used such a template:How to used such a template:

buffer<figure, 250> tbf; buffer<figure, 250> tbf; // declaration of object f// declaration of object f // a buffer for 250 figures// a buffer for 250 figuresbuffer<char,100> tbc; buffer<char,100> tbc; // a buffer for 100 characters// a buffer for 100 characters

Page 17: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

Identity of templatesIdentity of templates Two types derived from one template are identical only when Two types derived from one template are identical only when

all the arguments are identical. Otherwise they are different all the arguments are identical. Otherwise they are different types that have nothing in common. types that have nothing in common.

In the declarations below only objects In the declarations below only objects tbc0tbc0 and and tbc1tbc1 share share the same class (the same class (buffer<char, 100>buffer<char, 100>), others are of ), others are of different classes.different classes.

buffer<char,100> tbc0; buffer<char,100> tbc0; buffer<figure, 250> tbf0; buffer<figure, 250> tbf0; buffer<char,100> tbc1; buffer<char,100> tbc1; buffer<figure, 300> tbf1;buffer<figure, 300> tbf1;

Page 18: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

function templatesfunction templates

template <class T>template <class T> // outside of class declaration// outside of class declarationvoid exchange(T &x, T &y)void exchange(T &x, T &y) // not a method, but a function// not a method, but a function{{ T t=x;T t=x;

x=y;x=y;y=t;y=t;

}}

int a=7,b=8; int a=7,b=8; exchange(a,b); exchange(a,b); // the compiler will expand a template // the compiler will expand a template

// (if it is visible)// (if it is visible)

Page 19: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

function templates – examplefunction templates – example Create a family of functions to increment the first argument by Create a family of functions to increment the first argument by

the second (both are numbers)the second (both are numbers)

template <class t>template <class t>void increm(t &i, double d)void increm(t &i, double d) // will work for any numerical types // will work for any numerical types {{ // but calling increm(1, 1)// but calling increm(1, 1) i+=t(d);i+=t(d); // will cause 2 automatic conversions// will cause 2 automatic conversions};}; // waste of time// waste of time

template <class t, class d>template <class t, class d>void increm_optimised (t &i, const d delta) void increm_optimised (t &i, const d delta) // const will do no harm// const will do no harm{{ // and may be useful// and may be useful i+=t(delta);i+=t(delta);};};

Page 20: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

function templates – examplefunction templates – example Create a family of functions to increment the first argument by Create a family of functions to increment the first argument by

the second (both are numbers) the second (both are numbers) oror by 1 if the second arg is not by 1 if the second arg is not given.given.

// template <class t, class d>// template <class t, class d>// void increm_1 (t &i, const d delta=1)// void increm_1 (t &i, const d delta=1)// …// …

Trap!: At the callTrap!: At the callincrem_1(increm_1(3.14153.1415););

the compiler will not determine the type of d!the compiler will not determine the type of d!

Page 21: Templates. Class templates – why? Writing programs we often use abstract data types such as stack, queue or tree. Implementations of these types may be

function templates – examplefunction templates – example Create a family of functions to increment the first argument by Create a family of functions to increment the first argument by

the second (both are numbers) the second (both are numbers) oror by 1 if the second arg is not by 1 if the second arg is not given..given..

template <class t, class d>template <class t, class d>void increm_1(t &i, const d delta)void increm_1(t &i, const d delta){{ i+=t(delta);i+=t(delta);};};

template <class t>template <class t>void incremvoid increm_1_1(t &i)(t &i){{ i+=t(i+=t(11););};};