Sie sind auf Seite 1von 72

Contents of the Course

1.
2.
3.
4.

Advanced C++

Introduction
Basic C++ mechanisms
Advanced C++ mechanisms
The Standard Template Library

Jean-Paul Rigault
Polytechnic Engineering School, University of Nice
Computer Science Department
Email: jpr@polytech.unice.fr

13/06/09 15:52

2005-2006 Jean-Paul Rigault

13/06/09 15:52

2005-2006 Jean-Paul Rigault

Introduction
Summary

Advanced C++

Characteristics of C++
Some references

1. Introduction

13/06/09 15:55

2005-2006 Jean-Paul Rigault

1-1

Scandinavian school of object-oriented languages

1970

1980

Fortran

Support procedural (imperative) style


Support object-oriented style

Algol 60

Compiled language

1960

1990

2000

Hybrid language

1-2

Characteristics of C++
Origin and influences

Characteristics of C++

2005-2006 Jean-Paul Rigault

13/06/09 15:55

CPL

Ada 83
Algol 68
BCPL

Maximal static analysis


Promote programming safety and run-time efficiency

Ansi C
C with
classes

Upward compatibility with Ansi C

Simula 67

ML

C++

2005-2006 Jean-Paul Rigault

1-3

13/06/09 15:55

Std C++

Eiffel
Java

Smalltalk

13/06/09 15:55

C++ arm

CLU

Objective C

Lisp

Ada 95

CLOS
2005-2006 Jean-Paul Rigault

1-4

Characteristics of C++
Why is C++ difficult?

Language mechanisms are intrinsically complex

Need to master the fundamental concepts of programming


languages
An engineering trade-off, not an academic exercise
However, the language is consistent with its (clear) design
philosophy

2005-2006 Jean-Paul Rigault

Some references

Stress on architecture
Need to revisit centralized and purely functional reflexes

13/06/09 15:55

Object-orientation is a culture

Some references

1-5

(1)

International Standard for Information Systems


Programming Language C++
ISO/IEC 14882:2003
The C++ Programming Language (3rd Ed.)
Bjarne Stroustrup, 1997
The Design and Evolution of C++
Bjarne Stroustrup, 1994
Advanced C++
Programming Styles and Idioms
Jame O. Coplien, 1992
The C++ Standard Template Library
Nicola M. Josuttis, 1999

13/06/09 15:55

2005-2006 Jean-Paul Rigault

1-6

(2)

C++ Templates
The Complete Guide
David Vandevoorde and Nicolai Josuttis
Addison Wesley, 2003
Effective C++ CD
85 Specific Ways to Improve your Program Design
Scott Meyers, 2000
Effective STL
50 Specific Ways to Improve your Use of the Standard Template Library
Scott Meyers, 2001
Modern C++ Design
Generic programming and Design Patterns Applied
Andre Alexandrescu, 2001

13/06/09 15:55

2005-2006 Jean-Paul Rigault

1-7

Basic C++ Mechanisms


Summary

Advanced C++

Objects and types


The C++ class

2. Basic C++ Mechanisms

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-1

13/06/09 15:56

Objects and Types


Types in C++

Objects and Types


Instances, pointers, and references

Types of variables and constants in C++

Scalar types

2005-2006 Jean-Paul Rigault

(1)

Instance, pointer, and reference


All three available for all types (built-in or class)

Instance
int i, j;
string s1("hello");

Structures and unions


Classes

13/06/09 15:56

2-2

Three ways of accessing an object

Built-in types
Integral types: char, int and their variations, pointers
Real types: float, double and their variations
Enumerations (user defined)
These are also integral types

Class types (user defined)

2005-2006 Jean-Paul Rigault

An instance has value semantics: copying duplicates the


contents of the object (its value)
i = j;
string s2 = s1;

2-3

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-4

Objects and Types


Instances, pointers, and references

(2)

Pointer

Objects and Types


Instances, pointers, and references

A pointer instance has the address of another object as value

Reference

A reference is another name for an object (a synonym)

References do not have value semantics

int& ri = i;// ri and i denote the same object

int *pi = &i;

Pointers have value semantics

ri = 12;
// modify the object (i)
int j = 10;
int& rj = j;
ri = rj;
// set the value of ri (or i) to be
// the one of rj (or j), that is 10

The address is copied


pi = &j;
// modify the pointer value

The indirection operator (*) returns a reference to the object


pointed to
*pi = 3;

13/06/09 15:56

// modify the object pointed to (j)

2005-2006 Jean-Paul Rigault

Objects and Types


Instances, pointers, and references

2-5

2-6

(5)

References can be used as function return type

But beware of dangling references


string& f() {
string st = "hello"; // local variable!
return st;
}

Ensure we still reference something after the fonction returns


string& g(string& s) {
static string st = "hello";
if () return s;
else if () return st;
else return *new string("bye");
}

or to avoid spurious copies


class Big_Stuff { };
void print_Big_Stuff(const Big_Stuff&);

2005-2006 Jean-Paul Rigault

2005-2006 Jean-Paul Rigault

Objects and Types


Instances, pointers, and references

to allow effective parameter modification within the function

13/06/09 15:56

Reference behave somewhat like non null and constant


pointers, without the hassle of pointer syntax

13/06/09 15:56

void swap(int& a, int& b) {


int tmp = b;
b = a;
a = tmp;
}

(4)

References are mainly used for passing function


parameters

(3)

2-7

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-8

Objects and Types


Strong typing

(1)

Every object has a unique type


The type of an object must be known by the compiler when
the object is used
How is the type known?

Objects and Types


Strong typing

(2)

Type declaration

Symbolic and literal constants


const int N = 100;
const string GREET = "hello";

Either the object was declared in a type declaration


Or the type can be evaluated by the compiler

Variables
int i;
string str = "hello";

Functions (prototype as in Ansi C)


int f(int, double);
int printf(const char *format, ...);

2005-2006 Jean-Paul Rigault

13/06/09 15:56

Objects and Types


Strong typing

2-9

The type of an expression must be uniquely determined from


the type of its components (operands)

The type evaluation is recursive w.r.t. sub-expressions


The context plays no role for evaluating an expression type

A static (i.e., compile-time) conversion that the compiler can


perform automatically when needed

Standard conversions

x = (a + b) * 2 + c
Tx
Ta
Tb
int Tc

converted into

Built-in conversions of C and Ansi C

Between various integer variations and enumerations


Between integers and real numbers

Built-in conversions of C++: inheritance conversion

T(a+ b) * 2

2-10

Implicit conversion

Ta + b

2005-2006 Jean-Paul Rigault

Objects and Types


Strong typing but implicit conversions (1)

(3)

Type evaluation (for expressions)

13/06/09 15:56

From derived class to base class


For instances, pointers, and references

T(a+ b) * 2 + c
13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-11

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-12

Objects and Types


Strong typing but implicit conversions (2)

User defined conversions


From some type to a class

Objects and Types


Overloading

string::operator const char *() const;


// string const char *
string form = "%d %d\n";
printf(form, i, j);
2005-2006 Jean-Paul Rigault
of possibleambiguities!

2-13

13/06/09 15:56

Purpose of overloading resolution

Given a function call

... f(a1, a2, ..., an) ...


find a function with the same name matching the call

n is known, as well as the argument types T1, T2, ..., Tn


Context and return type play no role

Overloading resolution principle


1. Identify candidate functions
2. Among candidate functions, select the viable ones
3. Among viable functions, select the best match for the call

13/06/09 15:56

2005-2006 Jean-Paul Rigault

Objects and Types


Overloading resolution

(2)

Distinguishing two functions only from their return value type would
break the rule that says that the type of an expression is uniquely
determined from the type of its operands
int f();
double f();
int x = f();// which is the type of expression f()?

Objects and Types


Overloading resolution

The functions differ by their parameters (number and/or types)


The return value type plays no role

Defined by the cast operator

13/06/09
15:56
Beware

Same name for different functions


double cos(double);
complex cos(complex);

From a class to some other type

Overloading

Defined by constructors with one parameter

string::string(const char *);// const char * string


string s = "hello";
s = s + ", world!";// s = s + string(", world!")

(1)

Candidate functions
All functions visible at the
point of call and bearing the
same name as the one that is
called
Include possible instances of
function templates if their
argument deduction
succeeds
Relies on name lookup

2-14

(3)
Viable functions
All candidate functions that
can be considered for the call
Functions should have
adequate number of
arguments
There should exist
conversions between each
call argument and the
corresponding parameter of a
viable function

Relies on ranking possible argument conversions


2005-2006 Jean-Paul Rigault

2-15

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-16

Objects and Types


Overloading resolution
1. Exact match conversions

Identity

Lvalue transformations

Lvalue to rvalue
Array to pointer
Function to pointer

Qualification adjustment

short integers (including


enum and bool) to regular
ones

Floating point promotions

13/06/09 15:56

(4)

3. Other conversions

Integral conversions

Floating point conversions

Floating-integral conversions

Pointer and pointer to


member conversions

const and volatile

2. Promotion

Integral promotions

Objects and Types


Overloading resolution

include inheritance
conversions

Boolean conversions
4. User defined conversions

Constructors with one


parameter

Cast operators

void f(double&);
double x;
f(x);
// OK
f(3.14);
// NO
void g(const double&);
g(3.14);
// OK
class A {];
class B : public A {};
void f(A&);
B b;
f(b);

// OK

float to double
2005-2006 Jean-Paul Rigault

Objects and Types


Overloading resolution

2-17

13/06/09 15:56

1. Lvalue transformation
2. Promotion or other conversion (promotion is better)
3. Qualification conversion

2. User defined conversion sequences

3. Ellipsis conversion sequence

2005-2006 Jean-Paul Rigault

2-19

2-18

(7)

The best match viable function

1. Initial standard conversion sequence


2. One user defined conversion
3. Second standard conversion sequence

2005-2006 Jean-Paul Rigault

Objects and Types


Overloading resolution

(6)

1. Standard conversion sequence

13/06/09 15:56

Binding reference parameters


The argument must be an
appropriate initalizer for the
reference
It is forbidden to bind a nonconst reference to a
temporary
Inheritance conversions are
possible

(5)

The conversions applied to its arguments are no worse than the


conversions necessary for any other viable functions
There is at least one argument for which the conversion is
better than the conversion necessary for the same argument
when calling the other viable functions

std conv. seq. < user-def. conv. seq. < ellipsis conv. seq.
exact match < promotion < other conversions

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-20

Objects and Types


Overloading resolution

A remark on exact match


All exact match conversions
have the same strength,
except qualification
adjustment

void
void
void
void
void
void

(8)

int i;
const int *pci = &i;
int *pi = &i;
const string sc = "hello";
string s;

C programmer

OO programmer/modeler

f(pci);
// f(const int *)
f(pi); // f(int *)
g(sc);
// g(const
string&)
g(s);
// g(string&)

f(const int *);


f(int *);
g(const string&);
g(string&);
h(const string&);
h(string);

The C++ Class


Whats in a class?

Programming language specialist

Software engineer

// ambiguous

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-21

A model for creating instances


The set of its instances (the class extension)
An object (despite RTTI and templates)

An (abstract) data type

A name space
An encapsulation unit
A reuse unit

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-22

2-23

Member-functions
Access control
Initialization/finalization operations
Inheritance

However, any C++ class has an underlying C structure

Software engineer

2005-2006 Jean-Paul Rigault

A C++ class adds many features to a C structure

Programming language specialist

A natural extension of C structures (struct)

OO programmer/modeler

A name space
An encapsulation unit
A reuse unit

C++ Class: Extension of C Structure


Underlying C structure

C programmer

An (abstract) data type

13/06/09 15:56

The C++ Class


Whats in a class? C++ view

A model for creating instances


The set of its instances (the class extension)
An object

h(s);

A natural extension of C structures (struct)

Composed of the class data members


Representing the memory layout of the class instances
The size of which is the size of the class (sizeof)
Of course, the C++ programmer cannot manipulate this
structure directly

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-24

C++ Class: Extension of C Structure


Structures in C++

C++ Class: Extension of C Structure


Unions in C++

For backward compatibility, in C++, keyword struct is


almost equivalent to class

A struct can have constructors, destructors, memberfunctions, access control labels, etc.
Default access control for members is public for struct (its
private for class)
Default access control for derivation is public for struct
(its private for class)
struct MyStruct : AnotherStruct { // public
string s;
// public
private:
int n;
// private, of course
};

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-25

C++ Class: Model for Creating instances


Creating/deleting objects in C++

Since the type of the current member of the union is not


memorized, the compiler would not know what to copy, to
destroy...

2005-2006 Jean-Paul Rigault

13/06/09 15:56

Where?

Object creation

The role of a class constructor

Lifetime

1. Finalizing the object


The role of the class destructor

2.Returning memory

The two steps cannot be dissociated for C++ class instances

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-27

Scope

Block
automatic deletion

Block

Statically
allocated objects

Data
segment

Whole program
execution
automatic deletion

Block (static)
Class (static)
File (static)
Program (extern)

Dynamically
allocated objects

Heap

From new to delete


no automatic deletion

Scope of the
pointers that give
access to them

Exception objects

Heap?

From throw to last


catch
automatic deletion

Catch clauses

Object deletion

2-26

Automatic objects Stack

4 different ways

2.Initializing the object

An union is defined as a struct where all members have the


same address
Unions can have constructors and destructors, acccess control
labels, (non static) member-functions
Note that a C++ class with constructors, destructor, or copy
assignment cannot be a member of an union

C++ Class: Model for Creating instances


Memory allocation, lifetime, scope
(1)

1. Allocating memory

What about C union in C++?

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-28

C++ Class: Model for Creating instances


Memory allocation, lifetime, scope
(2)
// File f1.cpp
extern int glob;
static double PI = 3.14;

// File f2.cpp
extern string *f();
int glob = 12;

string *f() {
double x;
static int st = 10;
if () throw Exc();
return new string();

void g() {
try {
string *ps = f();
// ...
delete ps;

C++ Class: Model for Creating instances


Operators new and delete
(1)

}
catch (Exc& e) {
cout << e.what() << endl;
}

automatically allocated
statically allocated
dynamically allocated
thrown (exception)
13/06/09 15:56

Dynamically allocated objects is the only kind of objects


for which the programmer completely masters lifetime
The programmer has the possibility of redefining or
overloading the new and delete operators
Remember that

2005-2006 Jean-Paul Rigault

2-29

Overriding/Overloading new and delete

13/06/09 15:56

Per class

13/06/09 15:56

Override

Overload

For an individual object

For an individual object

For an array

For an array

For an individual object

For an individual object

For an array

For an array

2005-2006 Jean-Paul Rigault

2005-2006 Jean-Paul Rigault

2-30

C++ Class: Model for Creating instances


Operators new and delete
(3)
Overriding operators for individual objects, globally

Globally

although, in the case of class instances, the C++ compiler


automatically generates a call to the one of the class constructors

C++ Class: Model for Creating instances


Operators new and delete
(2)

new is just one (out of 4) ways of allocating objects


new is just a memory allocation operator

Prototypes
void *operator new(size_t);
void operator delete(void *);

Usage (as usual)

An idea of generated code (not totally accurate!)

A *pa = new A(...);


// allocation
A *pa = (A *)operator new(sizeof(A));
// initialisation (call to one constructor)
pa->A::A(...);
2-31

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-32

C++ Class: Model for Creating instances


Operators new and delete
(4)

Overriding operators for individual objects, per class

C++ Class: Model for Creating instances


Operators new and delete
(5)

Prototypes

class A {
public:
void *operator new(size_t);
void operator delete(void *);
// ...
};

2005-2006 Jean-Paul Rigault

2-33

13/06/09 15:56

C++ Class: Model for Creating instances


Operators new and delete
(6)
Overloading operator new

#include <new>
void *operator new(size_t, void *);
char buff[1000];
A *pa = new (buff) A();

The object is allocated at the given address (second parameter)


The programmer is responsible for allocating storage

13/06/09 15:56

2005-2006 Jean-Paul Rigault

For a class only


void operator delete(void *, size_t);
The second parameter is the size to deallocate
It is automatically filled by the compiler

Operator new with pre-placement (predefined)

2-34

Overloading operator delete

A *pa = new (t1, t2, ..., tn) A();

2005-2006 Jean-Paul Rigault

C++ Class: Model for Creating instances


Operators new and delete
(7)

void *operator new(size_t, T1, T2, ..., Tn);

The array element type must be default constructible

Thus, they cannot be virtual

13/06/09 15:56

Usage
A *pa = new A[n];
delete[] pa;

individual instances of A
individual instances of any class derived from A (that does not
define its own version of these operators)

These operators are static member-functions

The previous (either global or class) operators can only be used


for allocating individual objects
For arrays, one must use (and possibly override/overload)
void *operator new[](size_t);
void operator delete[](void *);

These operators supersede the global ones for allocating

Allocating/Deallocating arrays with new/delete

2-35

For a class or globally


void operator delete(void *, T1, T2, ..., Tn);
The extra parameters must be identical to the ones of an
overloaded new
This operator is called only from a new expression using the
overloaded new, when the object constructor throws an
exception
It cannot be called explicitely using a delete expression

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-36

C++ Class: Model for Creating instances


Constructors: a guarantee of initialization(1)

If a class has constructors, one if them will be invoked each


time an instance is created

Default default constructor

Just after memory allocation

If the constructor requires parameters they must be


provided when creating objects
If an instance is constructed without any constructor
parameters, its class must be constructible by default

C++ Class: Model for Creating instances


Constructors: a guarantee of initialization(2)

Either it has a default constructor (a constructor without any


parameters)
Or it has no constructors at all and all its base classes and all its
data members must be constructible by default (see next slide)

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-37

class A {
private:
A() {}
};

class C : public A {
private:
B _b;
};

class B {
public:
B(int);
};

C::C()
: A(), _b() // impossible!
{}

13/06/09 15:56

C++ Class: Model for Creating instances


Constructors: a guarantee of initialization(3)

All created objects have the guarantee of initialization


(call to one constructor)

Static objects are destroyed at the end of the program


execution (exit())

Automatic objects are created at the point where they are


defined in their block
Dynamic objects are created by the call to new
Exception objects are created by the call to throw

2005-2006 Jean-Paul Rigault

2-39

2-38

All objects have the guarantee of finalization (call to the


destructor) except dynamically allocated ones

C++ does not define any order for static initialization across
several compilation units

13/06/09 15:56

2005-2006 Jean-Paul Rigault

C++ Class: Model for Creating instances


Destructor: finalizing objects
(1)

Static objects are created at the start of program execution

When a class has no constructors, the C++ compiler tries to


synthesize a default constructor, by default
The process may fail leading to a compile-time error

C++ does not define any order for static destruction across
several compilation units

Automatic objects are destroyed at the end of their block of


definition
Exception objects are destroyed when they are no longer
needed (end of the last catch clause)
Dynamic objects must be deleted by explicitly calling delete

Destruction occurs in reverse order of creation

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-40

10

C++ Class: Model for Creating instances


Destructor: finalizing objects
(2)

If a class has no destructor, the C++ compiler will try to


synthesize a default destructor

C++ Class: Model for Creating instances


Construction/Destruction order
(1)

Construction order (for complex object)


1. Construction of base classe(s)
2. Construction of class own members

Call the destructors of own data members


Call the destructors of all base classes

The data members that the class owns by value

3. Constructor body

Destruction order (inverse order)


1. Destructor body
2. Destruction of class own members
3. Destruction of base classe(s)

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-41

C++ Class: Model for Creating instances


Construction/Destruction order
(2)

Base classes are constructed in the order of the derivation


list
Data members are constructed in the order of their
declaration in the class definition

Attention! DANGER !

2005-2006 Jean-Paul Rigault

2005-2006 Jean-Paul Rigault

2-42

C++ Class: Model for Creating instances


Construction/Destruction order
(3)
class B {public: B(int = 0);};

class A {private: int _p;


public:
A(int = 0);
// ...
};

class A1 : public A {
protected: B _b1;
public:
A1(int i = 0, int j = 1)
: _b1(i), A(j) {...}
// ...
};

class B : public A1, public A2 {


private:
int *pt;
int dim;
public:
B(int n) : dim(n), A1(n), pt(new int[dim]) {...}
// pt(new int[n]) would be correct!
};
13/06/09 15:56

13/06/09 15:56

A1

_b1

B
_b2

A2

class A2 : public A1 {private: B _b2;};

2-43

A1 a1(2, 3);

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-44

11

C++ Class: Model for Creating instances


Construction/Destruction order
(4)
class B {public: B(int = 0);};

class A {private: int _p;


public:
A(int = 0);
...
};

class A2 : public A1 {private: B _b2;};


A2 a2;

A2:A2()
: A1(),
_b2()
{}

default default
constructor

2005-2006 Jean-Paul Rigault

2-45

Underlying C structure: the values


Member and friend functions: the operations

Instances, with value semantics if needed

Copy operations can be user defined

2005-2006 Jean-Paul Rigault

2-47

2-46

(1)

Objects or functions common to all instances of a class


Beware: initialization of static data members
Simple declaration.
No initialization is possible here

// File A.cpp
string A::st("hello");
// ...

All type constructions: constant instances, pointers and


references to instances, arrays of instances
Possibility of defining operators (expression syntax)

13/06/09 15:56

// File A.h
class A {
private:
static string st;
// ...
};

Objects common to all instances: static members


Regard instances as first class citizens

2005-2006 Jean-Paul Rigault

C++ Class: Abstract Data Type


Static class members

Set of values and operations representing an abstraction of


an application domain entity

This default constructor is not called by default!!!

13/06/09 15:56

C++ Class: Abstract Data Type

that is for integral types (char, int and all their variations, and
pointers) and real types (float and double)
int g; // initialization at load time (0)
void f() {
int a = int();
// a initialized to 0
int b; // b not initialized by default!!
int *p1 = new int;// *p1 not initialized by default!!
int *p2 = new int();
// *p2 initialized to 0
int *p3 = new int(14); // *p2 initialized to 14
}

no constructor!

13/06/09 15:56

A default constructor is defined for built-in scalar types

class A1 : public A {
protected: B _b1;
public:
A1(int i = 0, int j = 1)
: b1(i), A(j) {...}
...
};

C++ Class: Model for Creating instances


Default constructor for built-in types

13/06/09 15:56

Static definition
Initialization (constructor call)

2005-2006 Jean-Paul Rigault

2-48

12

C++ Class: Abstract Data Type


Static class members

(2)

No guaranteed initialization order across compilation units

// file A.h

// file B.h

class A {
public:
static int _ist;

class B {
private:
static B _bst1;
static B _bst2;
public:
B(int);
};

int static fst() {


static int _fst = 12;
return _fst;
}

};

// file A.cpp
#include "A.h"

13/06/09 15:56

No new notation for operators


No modification of precedence or associativity
No modification of the number of operands
No redefinition for built-in types
All operators are redefinable, except

// file B.cpp
#include "B.h"
#include "A.h"
B B::_bst1(A::_ist);
B B::_bst2(A::fst());
// ...

int A::_ist = 12;


// ...

2005-2006 Jean-Paul Rigault

2-49

A::A(const A&);
Invoked by default each time an instance of A is initialized from
another instance of A

Simple initialization
Passing parameters and returning from functions by value
Default copy of classes with no copy constructor (see later)

13/06/09 15:56

2-50

(2)

Copy during assignment


A a1(), a2();
a2 = a1;

Copy constructor

2005-2006 Jean-Paul Rigault

C++ Class: Abstract Data Type


Copy operations

(1)

Copy during initalization

sizeof ::
.*
?:

However, note that -> and ->* can be redefined

13/06/09 15:56

A a1();
A a2 = a1;

Preprocessor operators: #
##
Compile-time operators: typeid
The three following operators: .

// ??
// OK

C++ Class: Abstract Data Type


Copy operations

C++ Class: Abstract Data Type


Defining operators for a class

2005-2006 Jean-Paul Rigault

Copy assignment operator

const A& A::operator=(const A&);


Return type may vary (void, A&)
Invoked by default each time an instance of A is assigned to
another instance of A

2-51

Simple assignment
Default copy of classes with no copy assignment operator
(see later)

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-52

13

C++ Class: Abstract Data Type


Copy operations

(3)

An assignment is not an initialization

An assignment trap:

Copy assignment may often be defined in term of copy


construction

There is exactly one initialization throughout the entire life of


an object
Initialization is always possible (once) whereas assignment may
be forbidden (const objects)
Assignment must take care of the previous state of the object
whereas, for initialization, there is no such thing as a previous
state

C++ Class: Abstract Data Type


Copy operations: default copy

If a class has copy constructor(s) and/or assignment


operator, these functions are entirely responsible for
copying objects
Otherwise, default copy is performed memberwise

class B : public A {
int i;
char *pc;
string s;
// no copy operations
};
B b1();
B b2 = b1;
b1 = b2;

2-53

Note that i and pc are bitwise


copied

2005-2006 Jean-Paul Rigault

2005-2006 Jean-Paul Rigault

2-54

(3)

Synthesis failure of default copy operations


class A {
private:
const string s;
B& rb;
A(const A&);
};

2-55

The synthesis process may fail

C++ Class: Abstract Data Type


Copy operations: default copy

B& B::operator=(const B& b) {


*(A*)this = (A&)b; // !!
i = b.i;
pc = b.pc;
s = b.s;
return *this;
}

Each member is copied according to its own copy semantics


Base class(es) are considered as members during the copy
operation
The memberwise procedure is applied recursively
Built-in types are copied bitwise

13/06/09 15:56

(2)

B::B(const B& b)
: A((A&)b),
i(b.i), pc(b.pc), s(b.s)
{}

13/06/09 15:56

2005-2006 Jean-Paul Rigault

C++ Class: Abstract Data Type


Copy operations: default copy

The C++ compiler synthethises the needed copy operations


(default copy constructor, default copy assignment operator)

Beware when writing the assignment operator: x = x;

13/06/09 15:56

(1)

// const member
// reference data member
// private copy constructor

The const member or the reference prevent the synthesis of


the default copy assignment (but not of the default copy
constructor)
The private copy constructor prevents the synthesis of the
copy constructor for a class that contains an A by value

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-56

14

C++ Class: Abstract Data Type


Copy operations: value semantics

A class has value semantics if

C++ Class: Abstract Data Type


Copy operations: non copiable objects

Copy operations are defined (possibly by default)


Everything is as if each instance conveys its own value (lvalue/
rvalue as in C)

Value semantics is not incompatible with an


implementation using sharing

2005-2006 Jean-Paul Rigault

2-57

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-58

(2)
class A {
class B { };
B m(B);
friend void f(B);
// ...
};

// List::nb_lists
// List::N1, List::N2
// List::Cell

A::B A::m(B b) {
B b1;
// ...
}

// this->first
// this->last

Definition of class scope


The body of the class
definition
The body of the memberfunctions from the :: operator
of the function name
Friend functions are not
within the class scope

void f(A::B b) {
A::B b2;
// ...
}

// List::fst()
// this->List::method()

2005-2006 Jean-Paul Rigault

Of course, this forbids copy only outside the class


A bullet-proof solution is to declare the copy operations but
not to implement them: any attempt to copy will lead to a link
edition error

C++ Class: Name Space


Class scope
(1)

13/06/09 15:56

private:
Non_Copiable(const Non_Copiable&);
Non_Copiable& operator=(const Non_Copiable&);
// No definition (no body) for these operations
public:
Non_Copiable() {}
};

C++ Class: Name Space


Class scope

class List {
private:
static int nb_lists;
enum {N1, N2};
class Cell {
int info;
Cell *next;
// ...
};
Cell *first;
Cell *last;
public:
static void fst();
void method();
// ...
};

class Non_Copiable {

Example: class string with copy-on-write

13/06/09 15:56

To forbid copying objects for a class, make copy operations


(copy constructor and copy assignment operator) private

2-59

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-60

15

C++ Class: Name Space


Hierarchical name space with inheritance(1)

Name lookup
This is the
simple case
See also
namespaces
further

lookup into global


(namespace) names

lookup into the


class hierarchy

the function is not


a member-function

the function is a member


of a class
lookup into the
function parameter list

lookup into the


hierarchy of nested blocks

identifier to lookup
13/06/09 15:56

... id ...

2005-2006 Jean-Paul Rigault

2-61

C++ Class: Name Space


Hierarchical name space with inheritance(2)
class A {
public:
int i; int j; int n;
};
class B : public A {
private:
int j;
};
class C : public B {
private:
int k;
public:
void f(double);
};
13/06/09 15:56

C++ Class: Encapsulation Unit


Access control

Security: not in C++?


Reducing dependencies
Preserving class internal consistency

Class context: ontext: union of...

Outside class context

2-63

private: members exclusively private to the class


protected: member private to the class and its derivatives
public: members visible and manipulable within any context

private: protected and public members private


protected: public members protected
public: protected and public members remain so

Default is private for class, public for struct


Access control is on the basis of the class

2005-2006 Jean-Paul Rigault

2-62

Three levels of derivation: inherited member level in the


derived class

Class scope
Body of friend functions
Class scope of friend classes

13/06/09 15:56

2005-2006 Jean-Paul Rigault

Three levels of access control for members

Contexts for access control

void C::f(double n) {
k = 0;
// this-> k, C::k
n = 3.14;
// function parameter
j = 2;
// B::j, but not
// accessible here
i = 3; // A::i
i = ::i;
// ::i is global i
}

C++ Class: Encapsulation Unit


Access control levels

Motivations for access control

int i; // global variable

Except for protected members

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-64

16

C++ Class: Encapsulation Unit


Class derivation access and conversions
class A {
public:
void f(A);
};
class B : private A {
public:
void g() {
B b; f(b);
}
};

C++ Class: Encapsulation Unit


A remark on protected members

The implicit inheritance


conversion from derived to base
is allowed
public derivation: in any
context
private derivation: only
within the derived class
context
protected derivation: only
within the derived class and
its derivatives contexts

B b;
f(b); // forbidden
13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-65

C++ Class: Encapsulation Unit


Friendship

Friend function
A function that is not a
member of the class
But that has access to the
class private and protected
members
Friend class
All the friend class member
functions are friend of the first
class

Restriction on friendship
Not symmetric

Friends of my friend are not


my friends

Not inherited

A friend of B does not imply


B friend of A

Not transitive

13/06/09 15:56

(1)

class B1 : public A {};


class B2 : public A {
public:
void f();
};

2-67

B2
C

class C : public B2 {};


void B2::f() {
A a; B1 b1; B2 b2; C c;
prot = 1;
// OK : this->prot

b2.prot = 4;
// OK : b2 is a B2 !
c.prot = 5;
// OK : conversion C B2
// (a C is a B2)
a.prot = 2;
// KO : no conversion A
B2
b1.prot = 3;
// KO : no conversion B1
B2
2005-2006 Jean-Paul Rigault
13/06/09
15:56
}

protected is not
really intermediate
between public and
private!
2-66

C++ Class: Encapsulation Unit


Friendship
class A {
friend void f(A);
friend class B;
private:
int _priv;
protected:
int _prot;
};

It is impossible to impose a
friend to a class

2005-2006 Jean-Paul Rigault

B1

void f(A a) {
A a1;
a1._priv = a._priv;
}

Parents friends are not


childrens friends
Childrens friends are not
parents friends

class A {protected: int prot;};

13/06/09 15:56

(2)

class B {
friend void g();
private:
int _i;
public:
void m(A a) {
A a1;
a1._priv = a._priv;
}
};
void g() {
A a;
_i = a._priv;
}

2005-2006 Jean-Paul Rigault

// NO

2-68

17

C++ Class: Reuse Unit


Reuse through inheritance

C++ Class: Reuse Unit


Reuse through inheritance: polymorphism(1)
Figure
surface()
rotate()

Static reuse mechanism


Reusing the interface or the implementation?

Interface reuse (public derivation) should satisfy the


substitutability principle
B is a subtype of A if any instance of A may be replaced by an
instance of B
The substitutability principle expresses the static semantics of
inheritance (a.k.a. subtyping)
Implementation reuse often utilizes private inheritance

Ellipse
surface()

Rectangle
surface()

Circle

Square

rotate()
13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-69

13/06/09 15:56

C++ Class: Reuse Unit


Reuse through inheritance: polymorphism(2)

Abstract class

A class with no possible instance


Usually on top of a class
hierarchy
In C++, a class is abstract as
soon as it has a least one pure
virtual function
A pure virtual function (= 0)
has no implementation

Concrete class

class Figure {
public:
// pure virtual:
// class is abstract
virtual
double surface() const = 0;
// virtual, but not pure
// virtual
virtual void rotate();
};

A class with instances


Must (re)define/implement all
inherited pure virtual functions

13/06/09 15:56

2005-2006 Jean-Paul Rigault

Figure *pf = new Circle(...);


double s = pf->surface();
pf->rotate();
2005-2006 Jean-Paul Rigault

2-70

Any member-function can be made virtual except

constructors
static member-functions
member templates (see later)

In particular, the destructor can be virtual

Friend functions are not members; they thus cannot be


virtual

2-71

class Ellipse : public Figure {


public:
double surface() const {
return PI*a*b;
}
};

C++ Class: Reuse Unit


Reuse through inheritance: polymorphism(3)

// ...

class Figure {
public:
virtual double surface() const;
virtual void rotate();
};

and should be for abstract classes

at least in the class they are friend of


if they are members of some other class, they can be virtual in
this other class

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-72

18

C++ Class: Reuse Unit


Reuse through composition

(1)

Composing with an instance (composition by value)

C++ Class: Reuse Unit


Reuse through composition

Static composition
Different composites cannot share the component
The composite is responsible for its components,
it owns them
The lifetimes of the composite and its components are identical

Composition with a pointer or a reference

Possibly, dynamic composition


Make polymorphism possible when delegating
Sharing is possible
Objects (component and composite) may be independent

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-73

(2)
class B { };
class A {
B _b;
// by value
B* _pb;
// by pointer
B& _rb;
// by reference
public:
A(const B& b1, B& b2)
: _b(b1),
_pb(&b2), _rb(b2)
{}
};

13/06/09 15:56

_b

_pb

_rb

During A construction, b1 is
copied into _b (by B copy
constructor: value semantics)
During A destruction, the
destructor of B will be
invoked

2005-2006 Jean-Paul Rigault

2-74

C++ Class: Reuse Unit


Using class instances

Creation

Since the constructor cannot be virtual, the exact (static) type


of an object must be known when creating it

Implementation

Utilization (and destruction)

The exact type is known statically


Either the static type is known and the compiler generates the
appropriate function call (static binding)
Or, the class is polymorphic and only a super type needs to be
known

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2-75

19

Advanced C++ Mechanisms


Summary

Advanced C++

3. Advanced C++ Mechanisms

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-1

Exceptions
Motivation

Notify the user


Allow her to recover and resume the program at a suitable
point
Separate normal processing from exceptional one
Respect the C++ creation/deletion semantics

C functions setjmp()/longjmp() are not appropriate


because local objects with destructor must be destroyed properly

13/06/09 15:56

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-2

Exceptions
Basic mechanism

Exceptions are mandatory because of encapsulation


What can be done when an abnormal condition is detected
inside a class?

Exceptions
Generic functions and classes (template)
Run Time Type Information (RTTI)
ISO C++ casts
Multiple inheritance
Miscellaneous ISO C++ extensions
Pointers to class members
Name packaging (namespace)

2005-2006 Jean-Paul Rigault

3-3

main() {f();}
void f() {
try {
...
g();
}
catch (E1) {...};
catch (E2) {...}
}

void g() {
try {
...
h();
}
catch (E1) {...}
}

void h() {
if (...) throw E1();
else throw E2();
}
13/06/09 15:56

An exception is a temporary object


(of any copiable type)
When an exception is raised
(thrown) the current function is
exited, and the exception is
propagated upward, traversing (and
exiting) functions in the calling chain
The propagation is stopped by the
first try block with a catch for the
(type of) the exception
The catch clause (handler) is
executed;
If the handler does nothing special,
control is then transferred after the
try block (and all its catch clauses)

2005-2006 Jean-Paul Rigault

3-4

Exceptions
Basic mechanism: destruction of locals
void f() {
try {
string s;
g();
...
deletion of s
}
catch (E1) {...};
}

deletion of s1
void g() {
string s1("hello");
h();
...
}
deletion of s2

void h() {
string s2("salut");
...
if (...) throw E1();
}
13/06/09 15:56

Exceptions
Basic mechanism: rethrowing an exception
main() {f();}

If a function is traversed by a
propagated exception, all
automatic (local) objects are
properly destroyed (i.e., their
destructor gets invoked)
Nothing similar happens for
dynamically allocated objects
(those allocated by new)
Thus it is the programmers
responsibility to provoke the
destruction of dynamically
allocated objects (see later)

2005-2006 Jean-Paul Rigault

void f() {
try {
...
g();
}
catch (E1) {...};
}
void g() {
rethrow
try {
...
h();
}
catch (E1) {...; throw;}
}

3-5

13/06/09 15:56

The exception object is


automatically deleted at the end
of the block of its last catch

2005-2006 Jean-Paul Rigault

3-7

3-6

(1)

All members fully constructed before the exception is


thrown are deleted

2005-2006 Jean-Paul Rigault

Exceptions
Throwing exception in a constructor

If no try block in the calling chain has a catch clause for


the current exception, the standard function
terminate() is called
By default, terminate() simply calls abort()
But the user may provide her own version

13/06/09 15:56

In a catch clause, using throw


without parameter simply
propagates the current exception
object upwards the calling chain

void h() {
if (...) throw E1();
}

Exceptions
Basic mechanism: uncaught exception

The destructors of fully constructed components are correctly


called
Partially constructed sub-objects are not destructed

The object itself has not been constructed, thus its


destructor wont get called
It is indispensable to understand clearly in which order
constructions/deletions are performed
It is not a good idea to throw an exception from within a
destructor!

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-8

Exceptions
Throwing exception in a constructor
class A1 {
string id;
public:
A1(const string& s) : id(s) {}
};
class A2 {
int val;
public:
A2(int v) {
if (v == 0) throw Exc_A2();
}
};
class B : public A1, public A2 {
string name;
public:
B(const string& s, int v)
: A1(s), A2(v) {
name = s; throw Exc_B();
}
};
13/06/09 15:56

(2)

Fully constructed parts

v0

!
!

!
!

name
(~string())

~B()

~A1()
~A2()

2005-2006 Jean-Paul Rigault

3-9

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-11

(5)

Extension to regular (and member) functions


int f(int x)
try {
int y;
// ...
}
catch (E1) { x = 3; return x;}
catch (E2) { y = 3; return x;} // y not visible

Thus, no reference to base and instance members of the


constructed/destructed object is allowed in the handlers

Thus, even if the exception has been caught by the constructor/


destructor, the object is not considered as properly constructed/
destructed

3-10

Function try block (cont. 2)

The exception caught in the handler is automatically


repropagated to the caller

2005-2006 Jean-Paul Rigault

Exceptions
Throwing exception in a constructor

Beware: special behavior when used for constructors and


destructors
Base classes and members have been already destroyed when
entering the exception handlers (catch clauses)

Particularly useful for constructors (and destructors)


B::B(const String& s, int v)
try
: A1(s), A2(v)
{
name = s;
throw Exc_B();
}
catch (Exc_B) {...; cout << s << endl;}
catch (Exc_A2) {...}

13/06/09 15:56

(4)

Function try block (cont. 1)

(3)

Function try block

v=0

Exceptions
Throwing exception in a constructor

Exceptions
Throwing exception in a constructor

Here, just a syntactic convenience, no special behavior


Note that function parameters (but not function local variables)
are visible in the handlers

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-12

Exceptions
Throw list

Exceptions
Throw list, virtual functions, and inheritance

void f() throw (E1, E2);


// may throw E1 or E2 only
void g() throw ();
// should not throw
void h();
// may throw any exception

class A {
public:
virtual void f1();
virtual void f2() throw (E1);
virtual void f3()
throw (E1, E2);
virtual void f4()
throw (E1, E2);

C++ only requires a dynamic check

class E1 {};
class E2 {};
class DE1 : public E1 {};

It is possible to specify the list of exceptions that a


(member or regular) function may throw

Static checking is possible but delicate


If an exception forbidden by the throw list is thrown,
unexpected() is called (which calls abort() by default)

virtual void f5() throw ();


virtual void f6() throw (DE1);
virtual void f7() throw (E1);
};

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-13

For a same try block, catch clauses are scanned from top
to bottom
Type conformance must be exact, except that standard
conversions related to inheritance (only) are authorized
The temporary object created by throw may be retrieved
in catch, by value but also by reference

Above, polymorphism may be honored for e


It is a good idea to always catch by reference

My_Exception

System_Exc

Arithmetic_Exc

Overflow
IO_Exc

File_Exc

When needed, it should be the last catch clause

13/06/09 15:56

2005-2006 Jean-Paul Rigault

Network_Exc

File_Network_Exc
3-15

13/06/09 15:56

Underflow
Zero_Div

The form catch (...) captures all exceptions

void f4() throw (DE1, E2);


void f5();
// NO
void f6() throw (E1); // NO
void f7() throw (E1, E2);// NO
};
3-14

Exceptions
Organizing exceptions: catch resolution(2)

catch (Stack::exception& e) {cout << e.what();}

class B : public A {
public:
void f1() throw ();
void f2() throw (DE1);
void f3() throw (E2);

2005-2006 Jean-Paul Rigault

13/06/09 15:56

Exceptions
Organizing exceptions: catch resolution(1)

A virtual function redefinition


cannot add to its base definition
throw list

try {
// ...
}
catch (Overflow& ov) { }
catch (Arithmetic_Exc& e) {
cout << e.what();
}
catch (File_Exc) { }
catch (IO_Exc) { }
catch (...) {
cout << "unexpected";
}

2005-2006 Jean-Paul Rigault

3-16

Exceptions
Organizing exceptions: exception

Exceptions
Organizing exceptions: exception

(1)

exception

Defined in the ISO standard


class exception {
public:
exception() throw ();
exception(const exception&) throw ();
exception&
operator=(const exception&) throw ();
virtual ~exception() throw ();
virtual const char *what() const throw ();
};

13/06/09 15:56

2005-2006 Jean-Paul Rigault

domain_err

3-17

overflow_err

invalid_argument

length_err

range_err

out_of_range

It is not mandatory to use the standard exception hierarchy


One is free to define a specific exception inheritance tree with
dedicated mechanisms

13/06/09 15:56

2005-2006 Jean-Paul Rigault

Exceptions
Resource Acquisition is Initialization

class Stack {
public:
class Any_Exc : public My_Exception { };
class Full : public Exc { };
class Empty : public Exc { };
// ...
void push(int);
// ...
};

void f1()
{
FILE *fp = fopen("toto", "w");
// ...
fclose(fp);
}
void f2()
{
A *p = new A();
// ...
delete p;
}
void f3()
{
lock(&mutex);
// ...
unlock(&mutex);
}

try {
st.push(v);
}
catch (Stack::Full) { }
catch (Stack::Any_Exc) { }
2005-2006 Jean-Paul Rigault

runtime_err

logic_err

Exceptions
Organizing exceptions: naming scheme

13/06/09 15:56

(2)

3-19

13/06/09 15:56

3-18

(1)

Who is going to call fclose if an


exception traverses this function?

Who is going to delete p if an


exception traverses this function?

Who is going to release the mutual


exclusion lock (unlock(&mutex))
if an exception traverses this
function?

2005-2006 Jean-Paul Rigault

3-20

Exceptions
Resource Acquisition is Initialization
class My_File {
FILE *fp;
public:
My_File(...) {fp = fopen(...);}
~My_File() {fclose(fp);}
// ...
};

void f1()
{
My_File mf("toto", "r");
// ...
// No need to close
}

class My_Handle {
A *p;
public:
My_Handle(...) {p = new A(...);}
~My_Handle() {delete p;}
// ...
};

void f2()
{
My_Handle h(...);
// ...
// No need to delete
}

class My_Lock {
Mutex *_m;
public:
My_Lock(Mutex *m) :_m(m) {lock(_m);}
~My_Lock() {unlock(_m);}
// ...
};

void f3()
{
My_Lock l(&mutex);
// ...
// No need to unlock
}

13/06/09 15:56

(2)

Some operation should guarantee to throw no exception

3-21

e.g., destructors, operator delete...

13/06/09 15:56

This is largely a matter of context


while ((c = getchar()) != EOF) {...}

In a function, isolate the code that may throw an exception and


do the work off to the side, before committing

2005-2006 Jean-Paul Rigault

3-22

Exceptions should be reserved for exceptional situations!

Above, the end of file is an expected (and wished) event

Implement copy assignement from copy constructor


Operator += from + and =
Relational operators from operator < and ==
etc.

13/06/09 15:56

2005-2006 Jean-Paul Rigault

Exceptions
Exception are for exceptional situations!

(2)

Always use RAI when applicable, to avoid leaking resources


Do not return a value from a mutator member-function
Try to define related operators in an homogeneous way

If an operation terminates because of an exception, program


state remains unchanged
Sort of commit and roll-back strategy

Nothrow guarantee

Some tips

Dont leak resources in case of exceptions


The program should be left in consistent (but not necessarily
predictable) state

Strong guarantee

(1)

Basic guarantee

2005-2006 Jean-Paul Rigault

Exceptions
Exception-safe code

Exceptions
Exception-safe code

3-23

try {
read(fd, &data_size, sizeof(int));
read(fd, buffer, data_size);
}
catch(End_Of_File) {...}

Above something to read was normally expected; the input file is


likely to be badly formed. Indeed, here the end of file is
exceptional...

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-24

Generic Functions/Classes (template)


General picture

Possibility to create functions and classes templates


parameterized (mainly) with types
Two different mechanisms for functions and classes

Static resolution (compile and link time)

Generic Functions/Classes (template)


Function template: definition

Only one representation of identical operations, but on


different types

Although somewhat homogenized by ANSI C++


Thus the template parameters must be static entities
A type driven macro-processing facility

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-25

13/06/09 15:56

Generic Functions/Classes (template)


Function template: basic usage

int i, j;
double x, y;
j = Min(i, 3); // int Min(int, int)
y = Min(x, y); // double Min(double, double)
Implicit instantiation is within the responsibility of overloading
resolution

3-26

The previous form of Min is not suitable for C null


terminated character strings (char *)
Of course, the programmer may provide a regular function
that will supersede template instantiation

3-27

because most exact match precedes template instantiation


during overloading resolution
char *Min(const char *s1, const char *s2)
{
return strcmp(s1, s2) < 0 ? s1 : s2;
}

2005-2006 Jean-Paul Rigault

2005-2006 Jean-Paul Rigault

Generic Functions/Classes (template)


Function template: specialization

Instantiation of function templates is generally implicit

13/06/09 15:56

template <typename T>


inline T Min(T a, T b)
{
return a < b ? a : b;
}
T denotes here any C++ type (class or built-in)...
... as long as the type has operator< and a copy constructor
(possibly the default one)

Note that, technically, this is different from template


specialization (see later)

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-28

Generic Functions/Classes (template)


Function template: argument deduction (1)

Generic Functions/Classes (template)


Function template: eradicating C preprocessor?

Generic functions are perfect replacement for the


preprocessor macros with parameters

Argument deduction

#define Min(a, b) ((a) < (b) ? (a) : (b))

By the way: eradicate most preprocessor use in C++


#define N 100
#define F(a) ...
#define G(a) ...

const int N = 100;


inline F(int a) {...}
template <typename T>
inline T G(T a) {...}

3-29

template <typename T>


const T& Another_Min(const T&, const T&);

string s1, s2;


s = Another_Min(s1, s2);
adjustment

Lvalue transformation
Qualification adjustment

Derived to base (inheritance) conversions

It is not an error for argument deduction to fail


2005-2006 Jean-Paul Rigault

13/06/09 15:56

Generic Functions/Classes (template)


Function template: argument deduction (2)

const string sc1, sc2;


string s = Another_Min(sc1, sc2);

Exact match conversions

2005-2006 Jean-Paul Rigault

Part of overloading resolution

Only the following conversions are accepted

There may remain only lexical and syntactic uses of the


preprocessor

13/06/09 15:56

The process of matching the call arguments with the function


template parameter types
Determine with function to instantiate

Generic Functions/Classes (template)


Function template: argument deduction (3)

Modification of overloading resolution

Candidate functions

// identity match

Include possible instances of function template for which the


argument deduction succeeds

// qualification

3-30

If there is a template specialization for the corresponding argument


deduction, include it instead of the primary template instance

Viable functions

Best match

Unchanged
Prefer non-template over template in case of equal ranking

double x = Another_Min(3, 7.5);


// no acceptable conversion for argument deduction
13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-31

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-32

Generic Functions/Classes (template)


Explicit instantiation of function templates

Generic Functions/Classes (template)


Class template: definition
(1)

Needed when the compiler cannot guess how to instantiate


the template

template <typename T, int N> T f();


f();
// which value for N? what is T?
f<int, 10>();
// OK

template <typename Elem> class List {...};


template <typename Elem, int N>
class Fixed_Array
{
Elem tab[N]; // N must be a compile-time constant
// ...
};

double x = Min(5, 7.2);


// no match
double x = Min<double>(5, 7.2); // OK

Beware: possible syntactic ambiguities


template <int N> void f(int);
i = f<3>(j); // it can read as: (f<3) > (j)
i = template f<3>(j); // OK

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-33

13/06/09 15:56

Generic Functions/Classes (template)


Class template: definition

template <typename Elem>


void List<Elem>::List() {...}

2005-2006 Jean-Paul Rigault

3-34

Instantiation of class template must be explicit


List<int> l1;
List<List<int> > l2; // attention: > >

template <typename Elem>


void List<Elem>::append
(const Elem& e) {
// ...
}

Fixed_Array<double, 1000> fa1;


Fixed_Array<List<int>, 100> fa2;
List<Fixed_Array<List<char>, 10> > l3;

template <typename Elem>


void List<Elem>::prepend
(const Elem& e) {
// ...
}
13/06/09 15:56

2005-2006 Jean-Paul Rigault

Generic Functions/Classes (template)


Class template: instantiation

(2)
template <typename Elem>
class List {
public:
List();
void append(const Elem& e);
void prepend(const Elem& e);
// ...
};

One unique representation of a set of classes that differ


only by the types of objects they manipulate or possibly by
some constants

typedef List<int> List_int;


List_int l4;
3-35

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-36

Generic Functions/Classes (template)


Class template and class derivation
(1)

Both mechanisms are totally compatible

Generic Functions/Classes (template)


Class template and class derivation
(2)

template <typename T>


class A {...};
template <typename T>
class B : public A<T> {...};

Access to inherited names


When designating a member
inherited from a base class
template, full qualification
must be used

template <typename T>


class B : public A<T> {
void f() {
_i = 12; // KO
A<T>::_i = 12;
// OK
this->_i = 12; // OK
};

template <typename T>


class Shared : public T {int refcnt; ...};
class C : public A<int> {...};
template <typename T>
class D : public C {...};
13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-37

13/06/09 15:56

Generic Functions/Classes (template)


Class template and implicit conversions (1)

Template instances and implicit conversion

Breaking static type checking


Assume French (and
English) derives from
Human

Shoud the answer be yes, substitutability principle, contravariance


rule, and static type checking would be broken...

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-39

2005-2006 Jean-Paul Rigault

3-38

Generic Functions/Classes (template)


Class template and implicit conversions (2)

Since there exists an implicit conversion from int to double,


shouldnt be a List<int> implicitely convertible into a
List<double>?
Since a French is a Human (suppose), shouldnt a set of French
be implicitely convertible into a set of Human?
The answer is NO in both cases

template <typename T>


class A {
protected:
int _i;
// ...
};

Hence, French * is
implicitely convertible into
Human *

Suppose we allow implicit


conversion from
Set<French *> to
Set<Human *>
Static typing is broken!

13/06/09 15:56

void f(Set<Human *>& sh) {


sh.add(new English());
// OK since English are
// Human, after all
}
Set<French *> sf;
// ...
f(sf);// implicit conversion
// There is now an English
// among the French!

2005-2006 Jean-Paul Rigault

3-40

10

Generic Functions/Classes (template)


Class template and friendship

Generic Functions/Classes (template)


Class template and implicit conversions (3)

Type Theory says: when


overriding a function in a
derived class, one may
Enforce the return type:
T may be a subtype of T

class A {
// ...
T f(T1, T2, ..., Tn);
// ...
};

The friend function does not


depend on the template
parameters, in any possible way
Friendship with all (visible)
instances of the template

C++ allows it (covariance)

Relax the parameter type:


Ti may be a supertype of Ti

(1)

This is the contravariant rule,


a consequence of the
substitutability principle:
demand less, promise
more
C++ only allows Ti = Ti

13/06/09 15:56

void f() {
A<int> ai;
A<string> as;
A<A<double> > aad;
ai._i = 10;
as._i = 10;
aad._i = 10; // OK
}

class B : public A {
// ...
T f(T1, T2, ..., Tn);
// ...
};

2005-2006 Jean-Paul Rigault

3-41

13/06/09 15:56

Generic Functions/Classes (template)


Class template and friendship
(2)

The friend function does depend


on (some of) the template
parameters

Friendship only with instances of


the template with the same
effective template arguments

template <typename T>


class A {
friend void f(A<T> a) {
A<int> ai;
A<T> at;
ai._i = 10; // NO if T
// is not int
a._i = 10;
// OK
at._i = 10; // OK
}
private:
int _i;
// ...
};

Defining a friend function of a


class template
outside the class

int main() {
A<string> as;
f(as);
}
2005-2006 Jean-Paul Rigault

The function must be declared


before the class
The friend declaration must
specify that a function
specialization is intended
The friend function may be
(often, must be) defined after
the class

within the class

3-43

2005-2006 Jean-Paul Rigault

// OK
// OK

3-42

Generic Functions/Classes (template)


Class template and friendship
(3)

13/06/09 15:56

template <typename T>


class A {
friend void f();
private:
int _i;
// ...
};

The function is not injected into


the global namespace
But it will be found by Argument
Dependent Lookup (see
namespaces, further)

13/06/09 15:56

template <typename T>


void g(T t);
template <typename T1, typename T2>
class A {
friend void g<>(T1);

friend void h(T1 t1) {


// ...
}
};
template <typename T>
void g(T t) {
// ...
}

2005-2006 Jean-Paul Rigault

3-44

11

Generic Functions/Classes (template)


Class template: member template

Generic Functions/Classes (template)


Class template and static data members

(1)

Initialisation of static members of class template

Member template of a regular class


class A {
public:
template <typename U>
void mt(U u);
};
template <typename U>
void A::mt(U u) { ... }

template<typename T> class A {


static int _i;
static T _s;
// ...
};
template <typename T> int A<T>::_i = 0;
template <typename T> T A<T>::_s = T();

The initializations must be in the same scope as the definition


of the class
Omitting initialization causes a link-time error

A a;
a.mt(3);
a.mt("hello");
a.mt(3.5);

but only if the static members are used!

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-45

13/06/09 15:56

Generic Functions/Classes (template)


Class template: member template

Member template of a class template

template <typename T>


class A {
public:
template <typename U>
void mt(U u);
};

// A<int>::mt(char *)

2005-2006 Jean-Paul Rigault

3-46

Friend function template of a regular class

Friend function template of a class template


template <typename T>
class A {
template <typename U> friend void tf(U u)
{ ... } // must be defined inline!
// ...
};

Member templates cannot be virtual

13/06/09 15:56

2005-2006 Jean-Paul Rigault

class A {
template <typename U> friend void tf(U u);
// ...
};
template <typename U> void tf(U u, ...) { ... }

template <typename T> template <typename U>


void A<T>::mt(U u) { ... }
A<int> a;
a.mt("hello");

// A::mt(int)
// A::mt(char *)
// A::mt(double)

Generic Functions/Classes (template)


Class template: friend function template

(2)

Just a parametrized overloaded member function

3-47

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-48

12

Generic Functions/Classes (template)


Template parameters of templates

Generic Functions/Classes (template)


Class template: friend class template

A class template can be friend of


a regular class as well as of a
class template

class A {
template <typename>
friend class F;
private:
int _i;
};
template <typename T>
class B {
template <typename>
friend class F;
private:
T _t;
};
13/06/09 15:56

(1)

template <typename U>


class F {
public:
void m() {
A a;
a._i = 12; // OK
B<int> b1;
b1._t = 6; // OK
B<U> b2;
b2._t = U(); // OK
};

int main() {
F<double> fr;
fr.m(); // OK
}
2005-2006 Jean-Paul Rigault

3-49

13/06/09 15:56

void sort(int, double[]);


Sortable<double, sort> s(...);
template <typename T = int, int N = 10>
class Fixed_Array {...};

2005-2006 Jean-Paul Rigault

Forbidden template parameters


Local types
Constants of type real
Non-external pointers...

template <typename T>


class A { ... };

// Fixed_Array<double, 10>
// Fixed_Array<int, 10>

void f() {
class L { ... };
A<L> a; // NO
}

template <typename T> class My_Container { ... };


template <typename U, template <typename> class Container = My_Container>
class Something {
Container<string> _cs;
Container <int> _ci;
// ...
};
Something<int, vector> sth;
2005-2006 Jean-Paul Rigault

But not for classe templates only, not for function templates
3-50

Generic Functions/Classes (template)


Template parameters of templates
(3)

template <typename T, void (*SORT)(int, T[])>


class Sortable {...};

13/06/09 15:56

A type (built-in or class)


A static constant of any integral type
(this includes enumerations and also pointers to functions and
pointers to members)
Another class template

Default values are possible for template parameters

Generic Functions/Classes (template)


Template parameters of templates
(2)

Fixed_Array<double, 100> fa1;


Fixed_Array<double> fa2;
Fixed_Array<> fa3;

ISO C++ unifies the parameter possibilities for template


functions and classes
A generic parameter may be

3-51

13/06/09 15:56

template <double X>


class B { ... };

// NO

template <char *C>


class A { ... };
A<"hello"> a1; // NO
extern char c[];
// initialize it somewhere
A<c> a2; // OK

2005-2006 Jean-Paul Rigault

3-52

13

Generic Functions/Classes (template)


Template specialization: total

Generic Functions/Classes (template)


Template specialization: partial

It is possible to provide a specialized version of a class or


function templates
The specialized version supersedes template instantiation
template <>
class List<char *> {
// Something which should
// look like List<T> with T = char *,
// although this is not necessary
// (for C++)
};

Here, the specialization is total, since all template parameters


have been fixed

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-53

template <typename T, typename I>


class Vector {
T& operator[](I index);
};
template <>
// Total specialization
class Vector<void *, int> {
... void *& operator[](int index);
};
// Note: no template <>
void *& Vector<void *, int>::operator[](int index) { ... }
template <typename T>
// Partial specialization
class Vector<T *, int> {
... T*& operator[](int index);
};
template <typename T>
T *& Vector<T *, int>::operator[](int index) { ... }

Generic Functions/Classes (template)


Template specialization: rules

Templates are parsed twice


1. At the template definition

Member templates and regular function templates cannot

Note that both member templates and regular function


templates may be overloaded
The specializations must be in the same namespace as the
template definition

2005-2006 Jean-Paul Rigault

3-55

Verify basic syntax


Look up non-dependent
names

2. At instantiation

See namespace further

13/06/09 15:56

3-54

Generic Functions/Classes (template)


Principle of template parsing

Any function template (including members) or class


template may be totally specialized
Class templates only may be partially specialized

2005-2006 Jean-Paul Rigault

13/06/09 15:56

Point of instantiation:
where the compiler inserts
the substituted template
definition
Look up dependent names

2-phase lookup

13/06/09 15:56

Independent name
A name that does not
depend on any template
parameter
Dependent name
A name that explicitly depend
on (some) template
parameters
T::A
A<T>
A<T>::_i
C::m<T>

2005-2006 Jean-Paul Rigault

3-56

14

Generic Functions/Classes (template)


Dependent name lookup
(1)

When designating a dependent


name inherited from a base
class, full qualification must be
used
Indeed, in 1st-phase lookup,
the compiler cannot bind to
the exact base class, because
of possible (and yet to come)
template specializations of
classs A

template <typename T>


class A {
protected:
int _i;
// ...
};

template <typename T>


class B : public A<T> {
void f() {
_i = 12;
// KO
A<T>::_i = 12;
OK
this->_i = 12; // OK
};

2005-2006 Jean-Paul Rigault

13/06/09 15:56

Generic Functions/Classes (template)


Dependent name lookup
(2)

//

3-57

When designating a type nested


within a class designated by a
dependent name, one must use
the typename keyword
Indeed, in 1st-phase lookup,
the compiler cannot know
wether the name effectively
designates a type, because of
possible (and yet to come)
template specializations of
classs A

13/06/09 15:56

Generic Functions/Classes (template)


Template instantiation models

The C++ compiler generates (source) code when


instantiating function and class templates

The template mechanism is a (type-driven) macro-processing


Thus, for templates, the distinction between

13/06/09 15:56

(2)

Use the ISO C++ export facility?


Few compilers support it, yet

Inclusion model

a .cpp file containing (only) template implementation is (almost)


like a header file

3-58

Separation model

is immaterial

2005-2006 Jean-Paul Rigault

However the user (instantiator) of a class usually wish to


include only the class definition (.h)
How can the compiler find the implementation (.cpp)?

the interface (function prototypes, class definitions), usually in


header files (.h)
the implementation (function or member-function body
definitions), usually in a regular source file (.cpp)

template <typename T>


class B : public A<T> {
void f() {
C c; // KO (see before)
A<T>::C c; // KO
typename A<T>::C c;// OK
typename T::iterator it;
};

Generic Functions/Classes (template)


Template instantiation models

(1)

template <typename T>


class A {
protected:
class C {};
// ...
};

Put everything into the .h file or, equivalently, include the .cpp
file at the end of the .h file?
As of now, this is the safest way

It cannot be compiled separately


However, function and member templates are not inline by default
2005-2006 Jean-Paul Rigault

3-59

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-60

15

Generic Functions/Classes (template)


Template instantiation models

Separation model: the export


keyword
export applies to the
definition of a class or of a
function
The compiler must know
where to look for the files
containing the definitions

command-line option

export does not solve the


dependency problem

Client code still depend on


the .h file as well as on
the .cpp file

13/06/09 15:56

Generic Functions/Classes (template)


Template instantiation code generation (1)

(3)

In file A.h
export template <typename T>
class Stack {
public:
void push(T);
T pop();

file1.cpp

file2.cpp

file3.cpp

List<int> l1;
List<double> l2;
List<string> l3;
...

List<int> l1;
List<string> l2;
...

List<int> l1;
List<double> l2;
...

};

In file A.cpp
#include "A.h
template <typename T>
void Stack<T>::push(T t)
{ ... }
template <typename T>
void Stack<T>::pop(T t)
{ ... }

2005-2006 Jean-Paul Rigault

3-61

Each file is compiled separately (compilation unit)


Into which object file (.o) is the compiler going to generate
the template instance binary code?

13/06/09 15:56

Generic Functions/Classes (template)


Template instantiation code generation (2)

Binary code generation during template instantiation

cfront, the first C++ compiler from AT&T used this technique
the pre-link phase may be very long

Generate code in all compilation units and let a smart linker


recognize the duplication and factorize the code

Binary code generation: fundamental remark

The code will be duplicated across compilation units


The object and executable files may become huge

Let a pre-linker generate code as external functions

3-62

Generic Functions/Classes (template)


Template instantiation code generation (3)

Generate code as (C) static functions in all compilation units?

2005-2006 Jean-Paul Rigault

The automatic template instantiation generates code only for


functions and member-functions that are effectively used
(instantiated) in the program
This is a general rule in C++: a function/member-function
(template ort not) that is not effectively used does not need
to be defined

There should not be any link edition error (undefined symbol) in


this case

This is the preferred way on systems supporting the ELF (Extended


Library Format) binary format

Let the user decide: explicit template instantiation

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-63

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-64

16

Generic Functions/Classes (template)


Template instantiation code generation (4)

Sometimes, it may be desirable to force instantiating a


function template or whole a class templates

class B : public A {
public:
void f(); // no f() in A
};

class List<int>;
generate the whole implementation
void List<double>::append(const int&);
int Min<int>(int, int);

2005-2006 Jean-Paul Rigault

Run Time Type Information (RTTI)


Motivation

3-65

13/06/09 15:56

(1)

Use with a pointer (expression) p

Check at run-time that p points to an object of type T or


(publicly) derived from T; otherwise return the null pointer (0)

Use with a reference r


T& rt = dynamic_cast<T&>(r);

Run Time Type Information has not to be built-in, since we


have already virtual functions
However it is more comfortable and safer to delegate its
implementation to the compiler

2005-2006 Jean-Paul Rigault

3-66

T *pt = dynamic_cast<T *>(p)

That is to require information about the dynamic type of an


object: RTTI

13/06/09 15:56

2005-2006 Jean-Paul Rigault

Run Time Type Information (RTTI)


Operator dynamic_cast

Remarks

A *pa = ...;// may be pa points to a B?


pa->f();
// FORBIDDEN: no method f() in A
((B *)pa)->f(); // OK, but is it reasonnable?

(2)

C-casts are resolved at compile-time


We need a way to check the cast at run-time

class A { ... };

The binary code is generated in the object file (.o) of the


current compilation unit

13/06/09 15:56

(1)

Make downward cast safe

Explicit template instantiation

For instance when creating a library containing specific


template instances
template
//
template
template

Run Time Type Information (RTTI)


Motivation

3-67

Check at run-time that p points to an object of type T or


(publicly) derived from T; otherwise throw predefined
exception bad_cast

T must be a polymorphic type

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-68

17

Run Time Type Information (RTTI)


Operator dynamic_cast
class Figure {
public:
virtual void rotate(int);
virtual int surface() const;
virtual void draw() const;
};
class Ellipse : public Figure {
public:
Ellipse(Point c, int a, int b);
int a_axis() const;
int b_axis() const;
};
class Circle : public Ellipse {
public:
Circle(Point c, int r)
: Ellipse(center, r, r) {}
int radius() const;
};
13/06/09 15:56

Run Time Type Information (RTTI)


Class type_info and operator typeid(1)

(2)

Figure *pf1 = new Circle(c0, R);


Figure *pf2 = new Ellipse(c1, A, B);
Ellipse *pe;
Circle *pc;

x = pf1->a_axis(); // NO
pe = dynamic_cast<Ellipse *>(pf1);
// pe != 0
x = pe->a_axis();
// YES...
now

pc = dynamic_cast<Circle *>(pf2);
// pc == 0

char *p = dynamic_cast<char*>(pf1);
// does not compile since char is
// not polymorphic
3-69

13/06/09 15:56

Run Time Type Information (RTTI)


Class type_info and operator typeid(2)

Class type_info (#include <typeinfo>)

13/06/09 15:56

2005-2006 Jean-Paul Rigault

2005-2006 Jean-Paul Rigault

3-70

Run Time Type Information (RTTI)


Class type_info and operator typeid(3)

class type_info {
public:
virtual ~type_info();
bool operator==(const type_info&) const;
bool operator!=(const type_info&) const;
bool before(const type_info&) const; // !!
const char *name() const;
// No public constructor
// No public copy operator
};

A type descriptor (an instance of the predefined class


type_info) is associated with each type (and thus with each
class)
Operator typeid returns a reference to the type descriptor of
its parameter
const type_info& typeid(type-name);
// static resolution
const type_info& typeid(expression);
// dynamic resolution if needed

pc = dynamic_cast<Circle *>(pf1);
// pc != 0

2005-2006 Jean-Paul Rigault

Once dynamic_cast built into the language, the path is


short to dynamic type identification

Operator typeid always returns the exact (dynamic) type


of its expression
Figure *pf = new Circle(...);

3-71

typeid(pf) == typeid(Figure *)
typeid(*pf) == typeid(Circle)

// yes
// yes

typeid(pf) == typeid(Ellipse *)
typeid(pf) == typeid(Circle *)
typeid(*pf) == typeid(Figure)
typeid(*pf) == typeid(Ellipse)

//
//
//
//

13/06/09 15:56

2005-2006 Jean-Paul Rigault

no
no
no
no

3-72

18

Run Time Type Information (RTTI)


Class type_info and operator typeid(4)

Bad usage of RTTI

void f(Figure *pf)


{
if (typeid(*pf) == typeid(Ellipse))
// do what is needed for an Ellipse
else if (typeid(*pf) == typeid(Circle))
// do what is needed for an Circle
else if (typeid(*pf) == typeid(Rectangle))
// do what is needed for an Rectangle
else // ...
}

Run Time Type Information (RTTI)


Class type_info and operator typeid(5)
typeid and dynamic_cast behaves like virtual
functions

class A {public: A(); ...};


class B : public A {...};
A::A() {
if (typeid(*this) == typeid(B)) ...
// FALSE, even when constructing a B
if (dynamic_cast<B *>(this) != 0) ...
// still FALSE, even when constructing a B
}

In such a case, use virtual functions!

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-73

13/06/09 15:56

Operator dynamic_cast is
nice!
It has a greppable syntax
It has a perfectly defined (and
unique) purpose

Dynamically safe downward


casting

Replacing the C casts by new


casts
with greppable syntax
with a unique and welldefined purpose

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-74

ISO C++ Casts


Operator static_cast

ISO C++ Casts


Overview

A virtual function is statically bound when called from within a


base class constructor and destructor

dynamic_cast
the only cast that uses
dynamic information
static_cast
safe if compile-time
information is enough to
perform the cast
reinterpret_cast
convert between pointer
types or between pointers
and integers
const_cast
remove const!

2005-2006 Jean-Paul Rigault

T1 t1;
T2 t2 = static_cast<T2>(t1);

Respect const and access control


If the cast is possible with only static information, it returns the
correct value,

3-75

even in case of regular (non virtual) multiple inheritance


this cast must not be used in case of virtual multiple inheritance
for downward casting

This cast is absolutely safe and the result is always correct if the
cast forces an implicit conversion

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-76

19

ISO C++ Casts


Operator reinterpret_cast

ISO C++ Casts


Operator const_cast
void f(const char *s, volatile int *pv) {
char *pc = const_cast<char *>(s);
int *pi = const_cast<int *>(pv);
}

T1 t1;
T2 t2 = reinterpret_cast<T2>(t1);

T1 and T2 may have any pointer type or, more generally, any
integral type
This cast is intrinsically unsafe

however, it respects const

No adjustment of the value returned

The cast does not change the value, but reinterpret it in a new
type
The only sensible use is as a conversion relay (convert into some
type then, later, back to the original type)

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-77

Multiple inheritance
Reminders

2005-2006 Jean-Paul Rigault

Remember that the reverse conversion is an implicit one, possible


at compile-time, hence safe

If the object is actually constant or actually volatile, the result is


undefined!
2005-2006 Jean-Paul Rigault

13/06/09 15:56

3-78

Multiple inheritance
Regular (non virtual) multiple inheritance (1)

The same class cannot appear several times as a direct base


class
The inheritance graph must be acyclic (DAG)
Ambiguities are detected at compile time (provided that
they are effective) and must be statically resolved
If a class appears as a base class through several
inheritance paths, the default is to have (in the derived
class) as many copies of the base class as there are
inheritance paths
If only one copy is suitable, use virtual derivation

13/06/09 15:56

This cast removes constness and/or volatility


The target type must be the original type but without const or
volatile

3-79

C*
B1*
this pointer
adjustment

B1

B2

B1

B2*
B2

C own
members
13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-80

20

Multiple inheritance
Regular (non virtual) multiple inheritance (2)
C*
B1*

this pointer
adjustment

B1

B2*

B2

Ambiguities?
Call to A members
Implicit conversion
to A
Default, since it costs
nothing!

virtual

B1

B2

13/06/09 15:56

B1

A
B2
B2 own
members

3-81

13/06/09 15:56

C c;
c.f(); // no longer ambiguous!
A *pa = static_cast<A *>(&c);
// no longer ambiguous!

class A {
public:
void f() {}
};
class B1 : public A {};
class B2 : public A {};
class C : public B1, public B2 {};
C c;
c.f(); // ambiguous!
static_cast<B1&>(c).f(); // OK
// or override f() in C
A *pa = static_cast<A *>(&c);
// ambiguous!
A *pa = static_cast<A*>(
static_cast<B1 *>(&c));
2005-2006 Jean-Paul Rigault

Multiple inheritance
Virtual multiple inheritance

(1)

class A {
public:
void f() {}
};
class B1 : virtual public A {};
class B2 : virtual public A {};
class C : public B1, public B2 {};

2005-2006 Jean-Paul Rigault

B2

C own
members

Multiple inheritance
Virtual multiple inheritance
A

A
B1
B1 own
members

2005-2006 Jean-Paul Rigault

13/06/09 15:56

Multiple inheritance
Regular (non virtual) multiple inheritance (3)

3-82

(2)

Example
class Vehicle {
public:
virtual double speed() const { }
// ...
};
class Plane : virtual public Vehicle {...};
class Boat : virtual public Vehicle {...};
class Sea_Plane : public Plane, public Boat {...};
// We suppose the previous derived classes
// do not redefine speed()
Sea_plane sp(...);
v = sp.speed();
// No ambiguity here

3-83

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-84

21

Multiple inheritance
Virtual multiple inheritance

??

virtual

B1

B2

13/06/09 15:56

Construction of a virtual base class

struct A {
A() {}
};
struct B1 : virtual A {
B1() : A() {}
};
struct B2 : virtual A {
B2() : A() {}
};
struct C : B1, B2 {
C() : A(), B1(), B2() {}
};

2005-2006 Jean-Paul Rigault

Multiple inheritance
Virtual multiple inheritance

(3)

virtual

B1

B2

3-85

(5)

Virtual base classes must be constructed exactly once


(as any C++ object)
They are constructed before any regular base class
Thus they must

Multiple inheritance
Virtual multiple inheritance
Construction of a virtual base class
struct A {
A() {}
};
struct B1 : virtual A {
B1() : A() {}
};
struct B2 : virtual A {
B2() : A() {}
};
struct C : B1, B2 {
C() : A(), B1(), B2() {}
};
2005-2006 Jean-Paul Rigault

13/06/09 15:56

3-86

Multiple inheritance
Virtual multiple inheritance
A* C*
B1* B2*

B1

(6)
A
B1 own
members
B2 own
members

offset
adjustment

virtual

Either be constructible by default


Or be (explicitly) constructed by any (concrete) derivative,
whatever how deep this derivative is in the hierarchy

(4)

B2
B2::m

B1
B2

C own
members

Actually this is not the


real memory layout...
13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-87

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-88

22

Multiple inheritance
Virtual multiple inheritance

(7)

Multiple virtual base classes?

virtual

B1

Multiple inheritance
Virtual multiple inheritance

B2

virtual

(8)

The complexity of conversions and addressing explains why


virtual derivation is not the default in C++
Note that pointers to members take into account this
complexity
Operator dynamic_cast makes downward cast possible
for virtual base classes
static_cast does not give a correct result in case of virtual
inheritance

C1

D
13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-89

New keywords, digraphs and trigraphs


Really miscellaneous extensions
Explicit constructors
Mutable data members
Initialization of const static integers
Convariant return
Pointer to class members
Name packaging (namespace, using)

and
and_eq
asm
auto
bitand
bitor

continue
default
delete
do
double
dynamic_cast

if
inline
int
long
mutable
namespace

register
reinterpret_cast
return
short
signed
sizeof

typedef
typeid
typename
union
unsigned
using

bool
break
case
catch
char
class

else
enum
explicit
extern
false
float

new
not
not_eq
operator
or
or_eq

static
static_cast
struct
switch
template
this

virtual
void
volatile
wchar_t
while
xor

compl
const
const_cast

for
friend
goto

private
protected
public

throw
true
try

xor_eq

struct
13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-90

Miscellaneous ISO C++ extensions


Keywords

Miscellaneous ISO C++ extensions

2005-2006 Jean-Paul Rigault

13/06/09 15:56

3-91

already in Ansi C

13/06/09 15:56

bitand

specific to C++, strange

2005-2006 Jean-Paul Rigault

class

specific to C++
3-92

23

Miscellaneous ISO C++ extensions


Digraphs and trigraphs

Miscellaneous ISO C++ extensions


Really miscellaneous

Beware of the following character combinations


Trigraphs are replaced before any source processing
A digraph is equivalent to some character, but its spelling is preserved
(in particular within character strings)
Trigraphs
(Ansi C compatibility)

Support for European and extended characters


If the loop index is declared in the for clause, its scope is
limited to the loop body (including the for clause)
for (int i = 0; i < N; i++)
if (t[i] == x) break;
t[i]++; // NO: i is unknown here

Digraphs
(C++ specific)

Trigraph

Replacement for

Trigraph

Replacement for

Digraph

Equivalent to

??=

??!

<%

??/

??<

%>

??

??>

<:

??(

??-

:>

??)

%:

13/06/09 15:56

2005-2006 Jean-Paul Rigault

In the same spirit, variables may be defined in conditions


if (int c = ...) {/* c is known here */}
while (int c = ...) {/* c is known here */}

3-93

13/06/09 15:56

Miscellaneous ISO C++ extensions


Preventing constructor implicit conversion

class A {
public:
explicit A(int);
// ...
};
a = 5;
// implicit user conversion A(5) forbidden
A a = 3; // NO
A a(3); // OK
A a = A(3); // a complicated form for the previous
a = A(5);// OK
2005-2006 Jean-Paul Rigault

3-94

Miscellaneous ISO C++ extensions


Mutable data members

Explicit constructors (explicit)

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-95

Non constant members even in constant objects


(mutable)

Allow to reduce the number of casts removing const?


Similar to const and volatile
(but only applicable to class members)
class A {
mutable int refcnt;
void f() const {
refcnt++; // modification of refcnt
}
// ...
};

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-96

24

Miscellaneous ISO C++ extensions


Covariant return

Miscellaneous ISO C++ extensions


Initialization of const static integer members

Direct initialization of const static integer members

class Table {
const static int N = 10;
// OK
int t[N];
// OK
};
These are the only members that can be initialized on the fly
Note that they must be at the same time const, static, and
of some integral type

char, short, long, long long and their unsigned


variations, enum
but not pointers

13/06/09 15:56

2005-2006 Jean-Paul Rigault

Pointers to Class Members


Pointer to member-functions

3-97

class A {
T f(int, double);
};

class U : public T {
// ...
};

class B : public A {
U f(int, double);
};

13/06/09 15:56

2005-2006 Jean-Paul Rigault

(1)

class Window {
int width, height;
int cursor_x, cursor_y;
public:
void up();
void down();
void right();
void left();
void repeat( ??? , int n);
};
2005-2006 Jean-Paul Rigault

class T {
// ...
};

3-98

Pointers to Class Members


Pointer to member-functions

Define a function taking a member-function as parameter

13/06/09 15:56

When overriding a member-function in a derived class, it is


possible to restrict its return type (covariance)

(2)

What is the type of up, down... ?

Certainly not void (*)() because class membership must


be taken into account
Pointer to a member-function of class Window with no
parameter nor result:

void (Window::*)()

3-99

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-100

25

Pointers to Class Members


Pointer to member-functions

Pointers to Class Members


Pointer to data members

(3)

class A {
int x;
int y;
// ...
};

Using a pointer to member through a pointer


void Window::repeat(void (Window::*op)(), int n) {
for (int i = 0; i < n; ++i)
(this->*op)();
}

Using a pointer to member through an instance/reference


void afunction(void (WIndow::*op)(), Window& w) {
(w.*op)();
}

int A::*pmi = &A::x;


A a, *pa = &a;
a.*pmi = 12;
// a.x = 12
pmi = &A::y;
pa->*pmi = 27:
// pa->y = 17

Typedefing a pointer to member


typedef void (Window::*Movements)();
Movements tab[] = {&Window::up, &Window::down, ...};

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-101

13/06/09 15:56

Pointers to Class Members


Pointers to members standard conversion

2005-2006 Jean-Paul Rigault

3-102

Pointers to Class Members


Pointers to members properties

A pointer to a base class member can be implicity


converted into a pointer to a derived class member

Pointers to members are sort of portable offsets

class A {
int x;
// ...
};
class B : public A { ... };

They take care of pointer/offset adjustment in case of multiple


(virtual) inheritance

Pointers to member-functions always honor virtuality


(dynamic binding)

int A::*pma = &A::X


B b;
b.*pma = 12;
// OK: b.x b.A::x = 12

Note that this conversion goes into the direction opposite to


the other inheritance conversions

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-103

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-104

26

Name packaging (namespace)


Motivation

namespace My_Lib {
class List {...};
void f(int, double);
int f(char);
// ...
}

Avoid name collisions due to an unique global name space

Name packaging (namespace)


Definition

when merging programs


when using several libraries...

Classes were already name spaces

Explicit qualification (operator ::) was required outside the


class, though

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-105

13/06/09 15:56

Name packaging (namespace)


Using a namespace

Explicit qualification

Using declaration
using My_Lib::f;
f(3, 12.5);
int i = f('a');

2005-2006 Jean-Paul Rigault

Name packaging (namespace)


Backward compatibility

My_Lib::List l;
My_Lib::f(3, 12.5);
int i = My_Lib::f('a');

A namespace is open : it can be extended simply by opening


a new namespace clause with the same name
Namespaces can be nested

// import name f

(1)

Standard ISO C++ library are in a predefined name space


(std)
Standard Ansi C .h files are also part of ISO C++, but their
name is prefixed with c (e.g., <cstdio>, <cstring>,
<cctypes>...)

Using directive

3-106

All standard Ansi C functions are part of the std namespace


(prinft, sin...)

using namespace My_Lib; // import everything


List l;
f(3, 12.5);
int i = f('a');
13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-107

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-108

27

Name packaging (namespace)


Backward compatibility

string aGlobalString; // global variable


void f() {
cout << ::aGlobalString << endl;
}

thus the names they contain can be used without extra


qualification, as in C

Files without extension (e.g., <cstdio>, <string>)

they have the same contents as the corresponding .h file


but they do not end with the using directive
hence, the user must handle the namespace std qualification

The .h extension for std files is deprecated

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-109

Name packaging (namespace)


Namespaces and name lookup

Regular lookup
Namespaces
form just
another nesting
hierarchy
The using
directives and
declarations
import the
corresponding
names into
another
namespace

13/06/09 15:56

lookup into the


class hierarchy

the function is a member


of a class
lookup into the
function parameter list

It must be collision free


It is not to be confused with the standard namespace std
2005-2006 Jean-Paul Rigault

Name packaging (namespace)


Namespaces and name lookup

lookup into the


namespace hierarchy

the names of the top level namespaces


the global names that are not in a specific namespace

13/06/09 15:56

(1)

lookup into the global


namespace

the function is not


a member-function

The anonymous namespace contains

Beware: not all header files have the two flavours

Unary operator :: accesses the anonymous namespace

Files with a .h extension (e.g., <cstdio.h>, <string.h>)


they are terminated with a using namespace std directive

(2)

Standard C++ header files may come in two flavours

Name packaging (namespace)


The anonymous namespace

Problem when looking


up unqualified names
Regular lookup is not
able to find which f
is used
Here, we can of
course use full
qualification...
But it is not always
suitable

int main() {
X::A a;
f(a);
X::f(a);
std::cout << a;
X::operator<<(std::cout, a);
// not very nice, is it?
}

... id ...

2005-2006 Jean-Paul Rigault

(2)

namespace X {
class A { ... };
void f(A a);
std::ostream&
operator<<(std::ostream& os, A a);
}

lookup into the


hierarchy of nested blocks
identifier to lookup

3-110

3-111

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-112

28

Name packaging (namespace)


Namespaces and name lookup

Agument dependent lookup


(ADL) (cont.)

A.k.a. Koenigs lookup


When resolving an
unqualified name in a (nonmember) function call, look
into the namespaces and
classes associated with the
arguments
The candidate functions will
be the union of regular look
up and ADL ones

Name packaging (namespace)


Namespaces and name lookup
(3)

namespace X {
class A { ... };
void f(A a);
std::ostream&
operator<<(std::ostream& os, A a);
}

(4)

int main() {
X::A a;
f(a); // ADL finds X::f
std::cout << a;
// ADL finds X::operator<<

Agument dependent lookup


(ADL) (cont.)
ADL behaves as if the
name had been prefixed
by an associated
namespace
Except that all using
directives are ignored in
the associated
namespaces

namespace X {
template <typename T>
void f(T t) { ... }
}
namespace Y {
using namespace X;
class A { ... };
}
int main() {
Y::A a;
f(a); // f not found
Y::f(a); // f found by regular lookup

std::string s;
std::cout << s << std::endl;
// ADL finds std::operator<<
// for string and endl

}
13/06/09 15:56

2005-2006 Jean-Paul Rigault

Name packaging (namespace)


Namespaces and name lookup

Agument dependent
lookup (ADL) (cont.)
Since the nondependent names are
looked up in the union
of regular look up and
ADL, there are possible
ambiguities

3-113

13/06/09 15:56

Name packaging (namespace)


Namespaces and name lookup

(5)

#include ...
using namespace std;

template <typename T>


const T& min(const T&, const T&);
int main() {
string s1, s2;

Name hiding in nested


namespaces
Redefining a name in a
nested namespace hides the
outermost ones

string s = min(s1, s2);


// Regular lookup finds ::min
// ADL finds std::min
// Both are exact matches
// Thus the call is ambiguous

2005-2006 Jean-Paul Rigault

3-115

13/06/09 15:56

3-114

(6)

namespace X {
void f(int);
namespace Y {
void
//
void
//

and does not overload them

A hidden name is not


considered during name
lookup (regular or ADL)

13/06/09 15:56

2005-2006 Jean-Paul Rigault

f(double);
this f hides the one above
g() { f(3);}
always call Y::f(double)

}
}
int main() {
X::Y::g(); // calls X::Y::f
using namespace X;
using namespace X::Y;
f(3); // calls X::f
g(); // still calls X::Y::f
}

2005-2006 Jean-Paul Rigault

3-116

29

Name packaging (namespace)


Namespaces and name lookup

Name hiding in nested


namespaces (cont.)
A using declaration imports a
name, thus allowing to
overload it
The same remark also applies
to inheritance class
hierarchies

Name packaging (namespace)


Classes as namespaces

(7)

namespace X {
void f(int);

namespace Y {
using X::f;
void f(double);
// now f is overloaded
void g() { f(3);}
// calls X::f(int)
}

int main() {
X::Y::g();
using namespace X::Y;
f(3); // calls X::f
f(3.5); // calls X::Y::f
g(); // calls X::f
}
13/06/09 15:56

2005-2006 Jean-Paul Rigault

Name packaging (namespace)


Classes as namespaces

3-117

void f(int); // hiding inherited f


};
B b;
b.f('a'); // compilation warning: calls f(int)!
2005-2006 Jean-Paul Rigault

3-119

2005-2006 Jean-Paul Rigault

Name packaging (namespace)


Classes as namespaces

class A {
public:
void f(char);
};
class B : public A {
public:

it allows to import an inherited member-function to the local


class scope
or to adjust the access control level in the derived class of an
inherited member

13/06/09 15:56

(2)

Importing inherited members in the global scope

13/06/09 15:56

Classes are namespaces


Directive using namespace is forbidden for a class
But using declaration is possible

(1)

3-118

(3)

Importing inherited members in the derived class scope


class A {
public:
void f(char);
};
class B : public A {
public:
using A::f;
void f(int); // overloading inherited f
};
B b;
b.f('a'); // calls f(char)

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-120

30

Name packaging (namespace)


Classes as namespaces

(4)

Adjusting access control level of inherited members

class A {
public:
void f(char);
};
class C : private A {
public:

2005-2006 Jean-Paul Rigault

(5)

Adjusting access control level of inherited members


class A {
public:
void f(char);
};
class C : private A {
public:
using A::f;
};
c b;
c.f('a'); // f(char) is now also public in C

};
c b;
c.f('a'); // f(char) is not accessible

13/06/09 15:56

Name packaging (namespace)


Classes as namespaces

3-121

13/06/09 15:56

2005-2006 Jean-Paul Rigault

3-122

31

The Standard Template Library


Summary

Advanced C++

4. The Standard Template Library

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-1

Overview of the STL


Utilities
Containers and iterators
Algorithms
Character strings
Input-output streams
Numerics
The STL and exceptions
Header files

13/06/09 15:57

Overview of the STL


Purpose

Implementation limits
Standard function with a machine-dependent optimal
implementation

Non primitive, yet portable objects


Extensibility
Foundation for other libraries

Usable directly and easily


Efficient
Primitive
Complete
Extensible
Neutral policy

2005-2006 Jean-Paul Rigault

4-3

Compatible with base types


Support for all programming styles

Type-safe

13/06/09 15:57

4-2

Overview of the STL


Implementation constraints

Language run-time support


Implementation characteristics

2005-2006 Jean-Paul Rigault

No cast needed to use it

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-4

Overview of the STL


Organization

Namespace std
Header files

Utilities
Class pair

template <typename T1, typename T2>


struct pair {
T1 first;
T2 second;
// Constructors
pair();
pair(const T1&, const T2&);
template <typename U1, typename U2>
pair(const pair<U1, U2>& p);
};

Recover ANSI C header files


(<cXXXX> <XXXX.h>)

Library elements

Containers, iterators, algorithms


Character strings, input-output streams
General utilities, diagnostics
Basic run-time support
(Localization)
(Numerical elements)

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-5

Used to implement Resource Acquisition is Initialization (RAI)

Copy of auto pointers:


ownership transfer

Constructor is explicit
auto_ptr<A> ap = new A(...);

// Forbidden

It is forbidden to assign a regular pointer to an auto_ptr


Special copy operations

13/06/09 15:57

2005-2006 Jean-Paul Rigault

2005-2006 Jean-Paul Rigault

Utilities
Class auto_ptr

#include <memory>
void f() {
auto_ptr<A> ap(new A(...));
// use ap as a pointer
// Pointed to object automatically deleted
}

13/06/09 15:57

(1)

A smart pointer class

Other operations
Equality, relational operators
Convenience function template make_pair

template <typename T1, typename T2>


pair<T1, T2> make_pair(const T1&, const T2&);

Utilities
Class auto_ptr

Couple of values

When copying auto pointers,


ownership of the object pointed
to is transferred to the target
The object previously owned by
the target, if any, is deleted
The previous owner (source of
the copy) looses ownership and
its internal pointer is set to null
Thus copying or passing by
value modifies the source of the
copy

4-7

4-6

(2)
auto_ptr<A> ap1(new A());
void f(auto_ptr<A> ap) {
// ...
// object owned by ap deleted
}
ap1 = auto_ptr<A>(new A());
// Object previously owned by
// ap1 is deleted and ap1
// becomes owner of new one
f(ap1);
// ap1 has lost ownership and
// is now null!!

This is a violation of usual rules

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-8

Utilities
Various utilities

Containers and Iterators

Numeric limits: class numeric_limits<T>


Minimum and maximum functions: min() and max()

template <typename T>


const T& min(const T&, const T&);

template <typename T, typename Compare>


const T& min(const T&, const T&, Compare comp);
comp(a, b) should return true if a is less than b for the given
order relationship

Possibility to pass the comparison predicate as third parameter

template <typename T>


void swap(T&, T&);
2005-2006 Jean-Paul Rigault

4-9

Array with automatic (re)allocation

deque<T>

<deque>

Sequence with optimized indexing

list<T>

<list>

Doubly linked sequence (list)

<stack>

Last In First Out (LIFO)

queue<T>

<queue>

First In First Out (FIFO)

priority_queue<T> <queue>

begin()

(1)

iterator
p
--

rbegin()

end()

++
*p

Queue with priority (operator<())

list<int> L;
for (int i = 0; i < N; i++) L.push_front(i);
list<int>::const_iterator it;
for (it = L.begin(); it != L.end(); ++it)
cout << *it << ' ';

Associative containers
map<K, T>

<map>

Associative array without duplicate (K is the key)

multimap<K, T>

<map>

Associative array with duplicate (K is the key)

set<K>

<set>

Set (without duplicates) of K

multiset<K>

<set>

13/06/09 15:57

4-10

Model : sequence and extended pointer

rend()

Container adapters: Default container is deque (for priority_queue, it is vector)


stack<T>

2005-2006 Jean-Paul Rigault

Containers and Iterators


Iterators

Basic containers (a.k.a. Sequences)


<vector>

Specific member functions


Parametrized memory allocation scheme (template
parameter)

13/06/09 15:57

Containers and Iterators


Different Types
vector<T>

Common member functions


Iterators

template <typename T,
typename Allocator = allocator<T> >
class list {...};

Swap values: swap()

13/06/09 15:57

Homogeneous contents
Homogeneous interface

Set (with duplicates) of K (a.k.a. Bag)


2005-2006 Jean-Paul Rigault

4-11

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-12

Containers and Iterators


Iterators

(2)

Reverse iteration

Containers and Iterators


Iterators

Using iterators as interval bounds (range)


list<int> L;
list<int>::iterator it;
int n;
// ...
for (n = 0, it = L.begin();
(it = find(it, L.end(), 3)) != L.end();
++it)
{
n++;
}

Use a reverse iterator

list<int>::const_reverse_iterator rit;
for (rit = L.rbegin(); rit != L.rend(); ++rit)
cout << *rit << ' ';

Non const iterator

Allow modification of container elements

list<int>::reverse_iterator rit;
for (rit = L.rbegin(); rit != L.rend(); rit++)
*rit = 10;
13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-13

Input iterator
Move forward only (++)
Provide read only access
Cannot process the same
element several times
Output iterator
Move forward only
Provide read/write access
Do not have comparison
operators
Forward iterator
Both input and output
Have comparison operators

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-14

Containers and Iterators


Pure Abstraction and Iterators

Bidirectional iterator
Move both ways (++, --)
Random access iterators
Bidirectional
Have arithmetic and
comparison operators

The STL mainly relies on the principle of Pure Abstraction

The model of iterator depends


on the type of the container
Member functions and
algorithms specify which model
they need

2005-2006 Jean-Paul Rigault

Iterator ranges always include left bound and exclude right one
([ [)

13/06/09 15:57

Containers and Iterators


Models of Iterators

(3)

4-15

If it walks like a duck and quacks like a duck, its a duck


This principle spares inheritance hierarchies

Iterators are smart pointers, they look like pointers


But pointers look like iterators, hence they are iterators
int tab[10];
vector<int> v(&tab[0], &tab[10]);
int *pi = find(&tab[0], &tab[10], 5);

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-16

Containers and Iterators


Common Members

Containers and Iterators


Common Members
(1)

(2)
Contruction and destruction

Member types
Cont::value_type

type of element

Cont c;

Create an empty container

Cont::iterator

value_type*

Cont c1(c2);

Cont::const_iterator

const value_type*

Create a container from another container with the same


value type

Cont::reverse_iterator

value_type*

Cont c(beg,end);

Create a container by copying the values in [beg, end[

Cont::const_reverse_iterator

const value_type*

c.~Cont()

Destructor

Cont::reference

value_type&

Cont::const_reference

const value_type&

Cont::allocator_type

type of memory allocator

13/06/09 15:57

2005-2006 Jean-Paul Rigault

Containers and Iterators


Common Members

Size operations

4-17

(3)

Comparisons
c1 == c2

Number of elements in the container

c.empty()

True if the container contains no elements

c.max_size()

Maximum possible number of elements

13/06/09 15:57

2005-2006 Jean-Paul Rigault

Containers and Iterators


Common Members

4-18

(4)

Iterator interface
Are the two containers equal (all their elements are
pairwise equal)

c1 != c2

Equivalent to !(c1 == c2)

c1 < c2
(and <=, >, >= )

Lexicographic comparison of containers (the value types


must be identical and it must have operator<())

c.begin()

Point to first element

c.end()

Point to just after last element

c.rbegin()

Point to first element in reverse order

c.rend()

Point to just after last element in reverse order

Insertion and removal

Assignments
c1 = c2

Assignment: copy all elements of c2 into c1; previous


elements of c1 are lost; the two containers must have the
same value type but may have different types

c1.swap(c2)

Swap internal data of c1 and c2; the two containers must


have the same type

swap(c1,c2)

Equivalent to c1.swap(c2)

13/06/09 15:57

c.size()

2005-2006 Jean-Paul Rigault

4-19

c.insert(pos,e)

Insert element of value e. The return value and the


interpretation of pos depend on the container type

c.erase(beg,end)

Remove all elements in the range [beg, end[

c.clear()

Remove all elements (revert to empty container)

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-20

Containers and Iterators


Specific members: vector, deque, list
Construction

Containers and Iterators


Specific members: vector, deque, list

(1)
v

dq

Cont c(n);

Create a container with n elements


initialized to the zero of their type

"

" "

c.at(i)

Return a reference to element at index i.


If it does not exist, throw out_of_range

" " "

Cont c(n,e);

Create a container with n elements


initialized to value e

"

"

"

c[i]

Return a reference to element at index i.


No check

" " "

c.capacity()

Total number of elements possible without


reallocation

"

"

"

c.front()

Return a reference to first element.


No check

" " "

c.reserve(n)

Reserve room for at least n elements

"

"

c.back()

" "

dq

Return a reference to last element.


No check

"

dq

c.resize(n)

Change size to n; if size grows new elements


are initialized to the zero of their type

" " "

c.resize(n,e)

Change size to n; new elements initialized to e

" " "

Set values

(2)

c.assign(n)

Assign the first n elements to the zero of


their type

" " "

c.assign(n,e)

Assign the first n elements to value e

"

13/06/09 15:57

"

2005-2006 Jean-Paul Rigault

4-21

Containers and Iterators


Specific members: vector, deque, list
Insertion and removal
c.insert(pos,n,e)

"

(3)
v

Insert n times value e at position


given by iterator pos (that is before)

dq

" " "

"

Access to elements

Resize

13/06/09 15:57

2005-2006 Jean-Paul Rigault

dq

4-22

Containers and Iterators


Specific members: list
Splice operations
c.unique()

Remove duplicate consecutive values

c.unique(op)

Remove duplicate consecutive elements for which op() is true

c1.splice(pos,c2)

Move element at pos in c2 in front of element at pos in c1; c1


and c2 may be the same list

c1.splice
(pos,c2,beg,end)

Move elements in the range [beg,end[ in c2 in front of element


at pos in c1; c1 and c2 may be the same list

c.insert(pos,beg,end) Insert elements in range [beg,end[ at


position pos

" " "

c.push_back(e)

Append element e

" " "

c.pop_back()

Remove last element. Return nothing.


No check

" " "

c.sort()

Sort elements with operator<()

c.push_front(e)

Prepend element e

"

" "

c.sort(op)

Sort elements with op()

c.pop_front(e)

Remove last element. Return nothing.


No check

"

" "

c1.merge(c2)

Merge elements of c2 into c1; c1 and c2 must be sorted before

Remove element at position pos.


Return an iterator to the successor

" " "

c1.merge(c2,op)

Same as above with op() instead of operator<()

c1.reverse()

Reverse list c1

c.erase(pos)
13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-23

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-24

Containers and Iterators


Specific members: stack and queues
Insertion and removal

Containers and Iterators


Specific members: associative containers (1)
s

pq

c.push(e)

Add an element with value e

" " "

c.pop()

Remove an element

" " "

c.top()

Return a reference to first element


No check

" "

c.front()

Return a reference to first element


No check

"

c.back()

Return a reference to last element


No check

"

" "
" "

2005-2006 Jean-Paul Rigault

4-25

Containers and Iterators


Specific members: associative containers (2)

Map and multimap

K, typename T,
Comp = less<K> > class map;
K, typename T,
Comp = less<K> > class

Can be changed by setting template parameter Comp


Or at construction time

No duplicates of the values of K in a map

13/06/09 15:57

K is the value type


Self-sorted (by default operator<())

Can be changed by setting template parameter Comp


Or at construction time

No duplicates of the values of K in a set

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-26

Containers and Iterators


Specific members: associative containers (4)

2005-2006 Jean-Paul Rigault

Cont c(op);

Create an empty container with op() as sorting criterion

Cont
c(beg,end,op);

Create a container by copying elements in range


[beg,end[ with op() as sorting criterion

Accessors

K is the key type


The value type is pair<const K, T>
Self-sorted w.r.t. K (by default operator<())

template <typename K, typename Comp = less<K> >


class set;
template <typename K, typename Comp = less<K> >
class multiset;

Construction

template <typename
typename
template <typename
typename
multimap;

Set and multiset

Internal container is a deque by default for stack and queue,


a vector for priority_queue
For priority queues, sorting is in decreasing order w.r.t operator<())
This can be changed with template parameters

13/06/09 15:57

4-27

c.count(k)

Return number of occurrences of k

c.find(k)

Return an iterator on cell with k

c.lower_bound(k)

Return an iterator to the first possible location for value k

c.upper_bound(k)

Return an iterator to the last possible location for value k

c.equal_range(k)

Return a pair of iterators to the possible range for value k

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-28

Containers and Iterators


Specific members: associative containers

Containers and Iterators


Specific members: associative containers (6)

(5)
Insertion and removal
c.insert(k)

Insert element k, return iterator to position for


multiset and multimap and a
pair<iterator, bool> for set and map

c.insert(beg,end)

Insert all elements in range [beg,end[, return nothing

c.erase(k)

Erase all elements with value k

c.erase(pos)

Erase the element at iterator position pos. No return!

Maps and multimaps


map<string, int> m;
// ...
it = m.find("hello");
// *it is a pair<const string, int>
cout << it->first << ' ' << it->second;
it->first = "bye";
// NO!

Note that k is a constant for all associative containers

You cannot change the value of the key, since it is used to sort
the elements

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-29

Maps only

13/06/09 15:57

//
//
//
//
//

initially empty
new element ("hello", 3)
print 3
allocate new element
("bye", 0) and print 0

Default constructor

4-31

If no equality operator, less than is used :


a == b !(a < b) && !(b < a)

Vectors

Define the "zero" of the type

Copy operations
For ordered containers, less than operator (<)

No arithmetics (see valarray)


Specialization vector<bool> is defined

Sets
No set operations (union, intersection)

2005-2006 Jean-Paul Rigault

4-30

Constraints on the elements (value_type)

13/06/09 15:57

2005-2006 Jean-Paul Rigault

Containers and Iterators


Remarks

Associative array using T& operator[](K)


This operator allocates a node for the key k if not already in the
map
The second element is initialized to the zero of its type (T)
map<string, int> m;
m["hello"] = 3;
cout << m["hello"];
cout << m[bye"];

Usual insert also works, provided that one use pairs!


m.insert(m.begin(), make_pair("hello, 3));
Iterator m.begin() is just a hint

Containers and Iterators


Specific members: associative containers (7)

Value type is pair<const K, T>

Use algorithms on sorted collections

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-32

Containers and Iterators


Operation Complexity
Indexing

Insertion anywhere

O(1)

O(n)+

vector
list
deque

O(1)

Algorithms
Operation on head

O(1)

O(1)

O(1)

O(n)

O(1)

O(1)

O(n)

queue

O(n)

O(1)

O(log n)

O(log n)

map

O(log n)+

O(log n)+

set

O(log n)+
O(1)

array

O(1)

valarray

O(1)

bitset

O(1)

13/06/09 15:57

O(1)

O(n)+

O(n)+

O(1)+

2005-2006 Jean-Paul Rigault

4-33

Have other parameters indicating an action to perform on


each element of the sequence

Header file <algorithm>


2005-2006 Jean-Paul Rigault

4-34

(2)

Filtering a sequence
bool is_gt_4(int i) {
return i > 4;
}

list<int> L;
list<int>::iterator it =
find(L.begin(), L.end(), 7);

Algorithms on sorted collections


Numeric algorithms

Algorithms
Algorithms on Sequences

to specify their range of action


to retrieve the result

Simple modifying algorithms


Removing algorithms
Mutating algorithms
Sort and merge algorithms

13/06/09 15:57

(1)

Use iterators

Non-modifying algorithms
Modifying algorithms

O(1)

Algorithms
Algorithms on Sequences

O(log n)+

string

About sixty predefined algorithms

O(log n)+

multimap
multiset

O(1)+

stack
priority_queue

Operation on tail

either selecting elements


or modifying elements

list<int> L;
int n = count_if(L.begin(), L.end(), is_gt_4);

list<int> L;
list<int>::iterator it =
find(L.begin(), L.end(), 7);
13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-35

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-36

Algorithms
Algorithms on Sequences/Sets

Algorithms
Function-Objects

(3)

Transforming a sequence

int length(string s) {
return s.size();
}

(1)

Algorithms for_each, find_if, count_if... are


templates functions

template <typename InputIterator,


typename UnaryPredicate>
InputIterator find_if(InputIterator first,
InputIterator last,
UnaryPredicate pred)
{
InputIterator it;
for (it = first; it != last && !pred(*it); ++it)
{}
return it;

list<string> LS(10, hello );


vector<int> VI(LS.size());
transform(LS.begin(), LS.end(), VI.begin(),
length);

}
13/06/09 15:57

2005-2006 Jean-Paul Rigault

Algorithms
Function-Objects

2005-2006 Jean-Paul Rigault

Algorithms on Sequences/Sets
Function-Objects

either a pointer to a function


(such as is_gt_4)
or a class defining operator()

13/06/09 15:57

(2)

UnaryPredicate denotes a type that may be

4-37

4-38

(3)

A function-object is an instance of a class defining


operator()
list<int> L;
class is_gt_4 {
public:
bool operator()(int i) {return i > 4;}
};

A class of function-objects

In all cases the signature of the function should be


something like

is_gt_4 criter; // define an object


int n = count_if(L.begin(), L.end(), criter);

bool pred(InputIterator::value_type)

int n = count_if(L.begin(), L.end(), is_gt_4());


// call is_gt_4 default constructor
13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-39

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-40

10

Algorithms on Sequences/Sets
Function-objects

Algorithms on Sequences/Sets
Functionals

(4)

class Figure {
public:
void draw() const;
void rotate(int angle);
// ...
};
list<Figure> LF;
for_each(LF.begin(), LF.end(), &Figure::draw);

Predefined function-objects
negate<type>(p)
-- p
plus<type>(p1, p2)
p1 + p2
and minus, multiplies, divides, modulus
equal_to<type>(p1, p2)
p1 == p2
and not_equal_to
less<type>(p1, p2)
p1 < p2
and greater, less_equal, greater_equal
logical_not<type>(p)
!p
logical_and<type>(p1, p2) p1 && p2
and logical_or

13/06/09 15:57

2005-2006 Jean-Paul Rigault

Algorithms on Sequences/Sets
Functionals

4-41

Functionals are defined in <functional>

several special effects: handling pointers and references,


parameters passing

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-43

4-42

(3)

Function adapters for function-objects

here it turns a pointer to a member function into a


function-object taking a Figure as first parameter

2005-2006 Jean-Paul Rigault

Algorithms on Sequences/Sets
Functionals

mem_fun_ref is an example of a functional

Error !

Algorithm for_each expects a regular function f(Figure)


&Figure::draw is a pointer to a member function

13/06/09 15:57

(2)

for_each(LF.begin(), LF.end(),
mem_fun_ref(&Figure::draw));

(1)

it = find_if(l.begin(), l.end(),
bind2nd(greater<int>(), 35));
bind1st and bind2nd bind respectively the first and the
second parameter of a 2 parameters function-object , yielding a
function-object with one parameter less
not1 and not2 return the logical_not of a function-object
returning a boolean (respectively with 1 or 2 parameters)

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-44

11

Algorithms on Sequences/Sets
Functionals

(4)

Function adapter for ordinary functions

Algorithms on Sequences/Sets
Functionals

Function adapters can only be applied to function-objects, not


to pointers to ordinary function
ptr_fun turns a pointer to a regular function (with at most
two parameters) into a function-object
As a consequence all the function-objects adapters can be
applied to the resulting function-object

Function adapters for member-functions

2005-2006 Jean-Paul Rigault

Algorithms on Sequences/Sets
Functionals

4-45

Many other functionals and function-objects

vector<Figure *> vfp;


for_each(vfp.begin(), vfp.end(),
bind2nd(mem_fun(&Figure::rotate), PI/2));

see the STL documentation

2005-2006 Jean-Paul Rigault

4-47

4-46

(1)

Modify neither the collection itself nor the value of the elements
Require associated operations on the elements (equality, comparison...)

for_each()
count()
count_if
min_element()
max_element()
equal()
mismatch()
lexicographical_
compare()

13/06/09 15:57

2005-2006 Jean-Paul Rigault

Algorithms
Non-Modifying Algorithms

list<char *> ls;


it = find_if(ls.begin(), ls.end(),
not1(bind2nd(ptr_fun(strcmp), "hello")));

Turn a pointer to a member-function (pm) into a function-objet:


the current object is passed as a pointer

13/06/09 15:57

(6)

Composing function-object adapters

Turn a pointer to a member-function (pm) into a function-objet:


the current object is passed by reference

mem_fun(pm)

13/06/09 15:57

mem_fun_ref(pm)

(5)

13/06/09 15:57

Perform an operation on each element


Count number of elements with some value
(satisfying a condition)
Return the smallest (largest) element
Return whether two collections are equal
Return the frist element that differs in two
sequences
Lexicographic comparison of two collections
2005-2006 Jean-Paul Rigault

4-48

12

Algorithms
Non-Modifying Algorithms
find()
find_if()
search_n()
search()
find_end()
find_first_of()
adjacent_find()

Algorithms
Modifying Algorithms

(2)

Find the first element with some value (satisfying a


condition)
Search n consecutive elements satisfying a
condition
Search for first (last) occurrence of a subrange

Search for the first of several elements

Search for two consecutive elements that are equal

13/06/09 15:57

2005-2006 Jean-Paul Rigault

Algorithms
Modifying Algorithms

4-49

2005-2006 Jean-Paul Rigault

Sorting algorithms
Special form of mutating
algorithms
Sort a collection
Sorted range algorithms
Only operate on sorted
collections
Numeric algorithms
Apply numeric operations
on collections

2005-2006 Jean-Paul Rigault

Algorithms
Modifying Algorithms

4-50

(3)

Insert iterators

Special iterators for which ++ (and --) do allocate new


elements

deque<double> dq(10, 3.14); // 10 elements


list<double> ld; // empty by default
copy(dq.begin(), dq.end(), ld.begin());
// likely to crash!!

13/06/09 15:57

13/06/09 15:57

They may modify the order of the elements


And also the value of the elements themselves

Not a real removal (see


further)

Mutating algorithms
Change the order of
elements

(2)

The modifying algorithms never modify the number of


elements in the container

Simple modifying algorithms


Modify the elements
Create new collections
Removing algorithms
Remove elements from a
collection

(1)

inserter, back_inserter, front_inserter

deque<double> dq(10, 3.14); // 10 elements


list<double> ld; // empty by default
copy(dq.begin(), dq.end(), back_inserter(ld));
// new elements added at the end of ld

4-51

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-52

13

Algorithms
Simple Modifying Algorithms

Algorithms
Removing Algorithms

for_each()

Perform an operation on each element

copy()
copy_backward()

Copy a collection starting with first (last) element

transform()

Transform a collection into another collection or combine elements


of two collections to form a third one

merge()

Merge two sorted collections

swap_range()

Swap elements of two collections

fill()
fill_n()

Replace each (n) element(s) with a given value

remove_copy()
remove_copy_if()
unique()

generate()
generate_n()

Replace each (n) element(s) with the result of an operation

unique_copy()

replace()
replace_if()

Replace elements with a given value (that match a condition) with


another value

replace_copy()
replace_copy_if()

Same as above, except that the result goes into another collection

13/06/09 15:57

2005-2006 Jean-Paul Rigault

remove()
remove_if()

4-53

Associative containers do not support remove() nor unique()

13/06/09 15:57

Algorithms
Mutating Algorithms
reverse()
reverse_copy()
rotate()
rotate_copy()
next_permutation()
prev_permutation()
random_shuffle()
partition()
stable_partition()

Remove elements with a given value (satisfying a


condition)
In fact reorganize a collection so that it contains
the elements to keep in an initial subcollection.
Return the end of this initial subcollection
Copy elements that do not match a given value
(do not satisfy a condition) in another collection
Remove adjacent duplicates (works the same way
as remove())
Copy elements in another collection while
removing adjacent duplicates

2005-2006 Jean-Paul Rigault

Algorithms
Sorting Algorithms

Reverse the order of elements in a collection


(copying into another collection)
Circular permutation of the elements in a
collection (copying into another collection)
Permutate the order of elements

(1)

These algorithms sort the elements according to a sort


criterion

Bring the elements in a random order


Change the order of elements so that the ones
matching a condition are at the front
(preserving the relative order of the original
collection)

4-54

operator<() by default
or a binary predicate given as a (last) parameter of the
algorithm

Beware: sort() and stable_sort() cannot be used for


list

They require a random access iterator


Use the List::sort() member function instead

Associative containers do not support these operations

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-55

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-56

14

Algorithms
Sorting Algorithms
sort()
stable_sort()
partial_sort()
partial_sort_copy()
nth_element()
make_heap()
push_heap()
pop_heap()
sort_heap()
partition()
stable_partition()

13/06/09 15:57

Algorithms
Sorted Range Algorithms

(2)

Sort a collection (preserving order of equal


elements)
Sort until an initial subcollection is correctly
sorted (copying into another collection)
Sort a collection yielding two subcollections
separated by a given element
Heap manipulation (heaps are a special
representation of binary trees used in sorting
algorithms)

binary_search()

Return whether a collection contains an element

includes()

Return whether a collection is a subset of another one

lower_bound()
upper_bound()

Find the first element greater than or equal (strictly


greater than) a given value

equal_range()

Return the range of elements equal to a given value

merge()

Merge two collections

set_union()
set_intersection()

Copy set union (intersection) of two collections into a


third one

set_difference()

Copy all elements of a collection that are not part of


another one into a third collection

Change the order of elements so that the ones


matching a condition are at the front
(preserving the relative order of the original
collection)

set_symetric_difference()

Copy all elements that are part of exactly one collection


(out of two) into a third collection

inplace_merge()

Merge two consecutive collections

2005-2006 Jean-Paul Rigault

4-57

13/06/09 15:57

Algorithms
Numeric Algorithms

The notion of a character varies


STL character strings are template classes

parameterized by the characteristics of characters, their


traits

Compute the sum (or any other binary operation) of


the elements of a collection

inner_product()

Scalar product and similar things over two


collections

adjacent_difference()

Yield a collection consisting of the result of a binary


operation (default is difference) on consecutive
elements
Yield a collection consisting of the result of a binary
operation (default is addition) on all predecessors of
each element

partial_sum()

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-58

Character Strings

The numeric operations must be defined on the elements


They can be passed as a parameter to the algorithm
Or there are default ones

accumulate()

2005-2006 Jean-Paul Rigault

4-59

representation
comparison (collating sequence)
copy operations
input-output

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-60

15

Character Strings
Class basic_string

Character Strings
Example: strings as sequence

Template class

One usual specialization

Usual properties

string basic_string<char>

vector<char> vc;
string s = "hello, world";
copy(s.begin(), s.end(), back_inserter(vc));

Construction, destruction, conversion from char *


Copies (value semantics but copy on write)
All operations of vector

Indexing ([], at)

No substrings
Catenation (+, append)
Comparisons

All sequence properties: iterators, algorithms

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-61

2005-2006 Jean-Paul Rigault

13/06/09 15:57

ios_base

Type driven extensible IO system


Present in C++ nearly from the origin
Improvements in STL

4-62

Input-Output Streams
Classification

Input-Output Streams

Converting a character string into an array of characters

ios

Interface and semantics cleaned up


Better extensibility (manipulators)
Homogeneity with sequences (iterators)

streambuf

virtual
istream

ostream

iostream
ifstream istringstream

ostringstream

stringstream
13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-63

13/06/09 15:57

ofstream

fstream

2005-2006 Jean-Paul Rigault

4-64

16

Input-Output Streams
Stream Manipulators

Input-Output Streams
Stream Iterators

Special operations

int x, y, z, t;
cout << x << flush;
cout << x << endl;

// flush the stream buffer


// new line and flush

cout << hex << x;

// print x in hexadecimal

vector<string> v;
copy(istream_iterator<string>(cin),
istream_iterator<string>(),
back_inserter(v));
copy(v.begin(), v.end(),
ostream_iterator<string>(cout, ---));

cout << oct << x << hex << y << dec << z;
cout << t;
// x printed in octal, y in hexadecimal,
// z in decimal, t in decimal too (last
// state of the stream)
13/06/09 15:57

2005-2006 Jean-Paul Rigault

Streams, like all containers, can have iterators

4-65

13/06/09 15:57

Complex number (template classes)


Numeric arrays : valarray

Standard operations on vectors


Sequence operations, iterators
Vector slices

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-67

(1)

except for standard exceptions such as bad_alloc


(impossible to allocate memory)
or when explicitly required

Numeric algorithms: accumulation, scalar product...

4-66

STL is not supposed to throw exception for logical


problems in containers and algorithms

Algorithms

2005-2006 Jean-Paul Rigault

The STL and Exceptions


Exception guarantees

Numerics

Note that the default constructor (istream_iterator())


corresponds to end of file

Only one case: member-function at()

or user-defined exceptions (in element constructors or


operations used by member functions or algorithms)

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-68

17

The STL and Exceptions


Exception guarantees

4-69

All single element insertions or removals are transaction safe


Operations at the end are transaction safe
If user copy operations do not throw, all operations are
transaction safe

list

All list operations are transaction safe...


except remove[_if](), sort(), merge(), and unique()

13/06/09 15:57

2005-2006 Jean-Paul Rigault

The STL and Exceptions


Respect of preconditions

(1)

Iterators must be valid (next slide)


No dereferencing of an iterator that points to the end guard
Range iterator must be valid

Array based containers: vector and deque

Since the STL almost never throws exceptions, all operation


calls that do not respect their preconditions result in
undefined behaviour
Basic preconditions

2005-2006 Jean-Paul Rigault

The STL and Exceptions


Respect of preconditions

Node based containers: list and associative containers

No resource leak
No violation of container invariants

13/06/09 15:57

If an operation fails (throws), the container is left in its original


state
a.k.a. commit-and-rollback guarantee

(3)

Supplementary guarantees

either STL own destructors or user destructors

Some containers provide transaction safe operations

The STL offers Basic Guarantee in case of exceptions

(2)

The STL exception guarantees rely on the fact that


destructor never throw

The STL and Exceptions


Exception guarantees

4-70

(2)

Iterator validity

An iterator must be initialized before being used


As a side-effect of some container operations, iterators can
become invalid
E.g., for vector and deque, after insertion and removal, or
when reallocation takes place

Both iterators must point to the same container


The second iterator must be reachable from the first

If several source ranges are used, they must have at least as


many elements as the first one
Destination ranges must have enough elements

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-71

13/06/09 15:57

2005-2006 Jean-Paul Rigault

4-72

18

Header files

(1)

Containers

<vector> <list> <deque>


<queue> <stack> <map>
<set> <bitset>

General utilities

<utility> <functional>
<memory> <ctime>

Iterators

<iterator>

13/06/09 15:57

Algorithms

Header files

<algorithm> <cstdlib>

Diagnostics

<stdexcept> <cassert>
<cerrno>

Strings

<string> <cctype>
<cwtype> <cstring>
<cwstring> <cstdlib>

2005-2006 Jean-Paul Rigault

4-73

(2)

Input-output
<iosfwd> <iostream>
<ios> <streambuf>
<istream> <ostream>
<iomanip> <sstream>
<cstdlib> <fstream>
<cstdio> <cwchar>
Localization
<locale> <clocale>

13/06/09 15:57

Run-time support
<limits> <climits>
<cfloat> <new>
<typeinfo> <exception>
<cstddef> <cstdarg>
<csetjmp> <cstdlib>
<ctime> <csignal>
Numerics
<complex> <valarray>
<numerics> <cmath>
<cstdlib>

2005-2006 Jean-Paul Rigault

4-74

19

Das könnte Ihnen auch gefallen