Scuola Superiore Sant’Anna
Advanced Course on C++
IV
Giuseppe Lipari
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
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<T>
void swap (T &a, T &b) { T tmp = a;
a = b;
MyClass a;
MyClass b;
swap<MyClass>(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 templatestack/
• Only when a template is instantiated, the code is generated.
– If we do not use swap<T>, the code is never generated, even if we include it!
– if there is some error in swap<T>, the compiler will never find it until it tries to generate the code
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<T, int sz>
class Buffer { T v[sz];
int size_;
public:
Buffer() : size_(i) {}
};
Buffer<char, 127> cbuf;
Buffer<Record, 8> rbuf;
void f(int a) {
Buffer<char,a> c;
}
Default parameters
• Some parameter can have a default value
template<class It, class Cmp=less>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<T>
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<int>
swap(x, y); // calls swap<MyClass>
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 T> class List {…}
template<> class List<string> {...}
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
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
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<class It, class Cmp=less>
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
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
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 “errorreturnvalue”
– we can print the error and call exit();
• C++ provides an alternative: exceptions
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 }
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
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) {}
}
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) { 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
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
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
– http://www.cuj.com
• Guru of the week
– http://www.gotw.ca
• The Standard template library
– http://www.sgi.com/tech/stl
• Mumit’s STL Newbie guide
– http://www.nanotech.wisc.edu/~khan/software/stl/STL.newbie.ht ml
• And many other!!