Scuola Superiore Sant’Anna Advanced Course on C++ IV Giuseppe Lipari
2 Templates Your quote here
3 Templates Templates are the mean for providing generic programming Often, programmers keep doing the same things with slight modifications The most common example is containers –Implementing a list of integers or doubles is not so different –A find() algorithm for a container does not depend on the type of the object
4 Example Suppose we have to swap two integers int a = 2; int b = 4; int tmp = a; a = b; b = tmp; What if we want to swap two generic objects? void swap (int &a, int &b) { int tmp = a; a = b; b = tmp; } template void swap (T &a, T &b) { T tmp = a; a = b; b = tmp; } MyClass a; MyClass b; swap (a,b);
5 Templates Implementing generic containers is the most common use of templates –examples are in the std library, like vector, list, map, etc –see template-stack/ Only when a template is instantiated, the code is generated. –If we do not use swap, the code is never generated, even if we include it! –if there is some error in swap, the compiler will never find it until it tries to generate the code
6 Template instantiation The code for a template should be written all in the header file –it works exactly like inline: the code for the class is generated only when it is used According to Stroustrup (and to the standard), there is a way to write the implementation in the cpp file –you have to use the export keyword –most compilers do not support well this feature
7 Template parameters A template can have any number of parameter A parameter can be –a class, or any predefined type –a function –a constant value (a number, a pointer, etc.) template class Buffer { T v[sz]; int size_; public: Buffer() : size_(i) {} }; Buffer cbuf; Buffer rbuf; void f(int a) { Buffer c; }
8 Default parameters Some parameter can have a default value template sort(It begin, It end);
9 Function template An example of function template is the swap function –other examples are in the STL: sort, find, for_each, etc The compiler tries to automatically deduce the template arguments template void swap (T &a, T &b) { T tmp = a; a = b; b = tmp; } int a = 1; int b = 2; MyClass x,y; swap(a, b); // calls swap swap(x, y); // calls swap
10 Template specialization It is possible to specify the template parameters, all or in part, and provide a specialized implementation –For example, list of pointers is a more specialized case that a generic list. We can provide a special implementation for this special case template class List {…} template<> class List {...} template class List {…}
11 A brief explanation of iterators When you build a container, you need special functions to access the members and traverse the container –One solution could be to write special member functions, like getFirst(), getNext(), and so on –This solution is inflexible, for many reasons internal state for the container you can traverse in one way only generic functions, like sort, could not work in general –A better solution is to provide an additional std class, called iterator, to access the members with a unified interface
12 Iterator An iterator is like a pointer to an object, with restrictions –it can only point to element of a container –operator++() returns the next element in the container –operator*() returns the member itself Every container defines its own iterator class, the interfaces are the same –in this way, it is possible to write generic functions that use only iterators
13 Templates for specifying policies Suppose we want to write a generic sort, like in the STL sort –we only need a way to compare objects, we do not need the type of the object where to put this compare function? –we cannot put it in the container –we cannot put it in the object –we have to provide it separately template
14 Exercise Generalize your list, to contain any kind of object –it must be a template Then, write a Cmp class that compare two strings without considering capital letters –aaa should be equal to AAA Finally, use the my_find function defined in Template_stack/ to look for strings inside your list
15 Exception handling Don’t interrupt me while I’m interrupting - W.S. Churchill
16 Why exception handling The problem of signaling an error… Alternatives –returning an error code –setting a global error variable and returning -1 –exiting We need to write a lot of special purpose code for handling this special cases –we would like, instead, to write less code –see stack/
17 The list implementation You implemented operator[] for random access in the list What if the user specifies an out-of-range index? –we can specify a special “error-return-value” –we can print the error and call exit(); C++ provides an alternative: exceptions
18 Exceptions An exception is an object of a class representing an exceptional occurrence –This way, C++ uses the class mechanisms (like inheritance, etc.) to implement exceptions –The exception class has nothing to do with the other classes in the program An exception can be thrown with the throw keyword see exc_stack/
19 Try/Catch An exception can be caught inside a try/catch block try { // // this code can generate exceptions // } catch (ExcType1&e1) { // all exceptions of ExcType1 } catch (ExcType2 &e2) { // all exceptions of ExcType2 } catch (…) { // every exception }
20 Try/catch If the exception is not caught, then the program is aborted –this is necessary, since the compiler does not know what to do with that exception Usually, it is better to define a hierarchy of exception classes –For example, if you are writing a library for math processing, you can define a base MathExc exception class, and derive any other exception from that class
21 Exception and inheritance In this way, we can throw an object of type LogErr, and catch it as a MathErr class MathExc { string error; string where; public: MathErr(const string &e, const string &w) : error(e), where (w) {} virtual string what() { return error + “ “ + where;} }; class LogErr : public MathErr { public: LogErr() : MathErr(“Log of a negative number”, “log module”), n(a) {} }
22 Exceptions and inheritance This code will print “Log of a negative number - log module” –you can also pass any parameter to LogErr, like the number that cause the error, or the name of the function which caused the error, etc. void f(int i) { mylog(i); } try { // some code f(-5); } catch(MathErr &e) { cout << e.what() << endl; } double mylog(int a) { if (a < = 0) throw LogErr(); else return log(double(a)); }
23 Exception specification It is possible to specify which exceptions a function might throw, by listing them after the function prototype void f(int a) throw(Exc1, Exc2, Exc3); void g(); it means: f() can throw ONLY Exc1, Exc2, Exc3 if you do not put anything, it means that the function g() can throw ANY exception This helps the user of a library however, pay attention at listing all the exception that can be thrown
24 The memory is not deallocated! At this point, a is destructed Exception and memory allocation An exception will “unroll” the stack of a function void f() { A a; if (cond) throw Exc(); } void g() { A *p = new A; if (cond) throw Exc(); }
25 Exception safety There are many problem that pop up from not using exceptions properly –we have seen just one Too many to list here! –if you are interested, please refer to a more specialized book
26 Bibliography “The C++ programming Language” third edition, Bjarne Stroustrup, Addison-Wesley –now there is a special edition “Effective C++, 2nd edition: 50 specific ways to improve your programs and designs” Scott Meyers, Addison-Wesley “Effective STL” Scott Meyers, Addison-Wesley
27 Web sites C/C++ Users Journal – Guru of the week – The Standard template library – Mumit’s STL Newbie guide – And many other!!