161
C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon [email protected] Ericsson C++ Seminar

C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon [email protected] Ericsson C++

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 1

Chris [email protected]

EricssonC++ Seminar

Page 2: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 2

Advanced C++

9:00 - 10:30 Introduction to Templates

10:30 - 12:00 The new C++11 Standard (Part 1)

12:00 - 13:00 Lunch

13:00 - 14:30 Standard Template Library

14:30 - 16:00 Using the STL Efficiently

16:00 - 17:30 Boost (Part 1)

Ericsson C++Seminar

Page 3: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 3

Page 4: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 4

Copyright ©1994-2010 CRS Enterprises 4

Introduction to Templates

Template Functions

Template Classes

Specialization

Template MetaPrograms

Traits

Template Template Parameters

Page 5: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 5

Copyright ©1994-2010 CRS Enterprises 5

Generic Functionsint Max(int a, int b){

if (a > b)return a;

elsereturn b;

}

double Max(double a, double b){

if (a > b)return a;

elsereturn b;

}

string Max(string a, string b){

if (a > b)return a;

elsereturn b;

}

int Max(int a, int b){

if (a > b)return a;

elsereturn b;

}

double Max(double a, double b){

if (a > b)return a;

elsereturn b;

}

string Max(string a, string b){

if (a > b)return a;

elsereturn b;

}

• similar functions– ready to be converted to templates

• identify types– that can be made generic

int main(){

cout << Max(5, 8) << endl;cout << Max(5.1, 8.3) << endl;cout << Max("Red", "Blue") << endl;

}

int main(){

cout << Max(5, 8) << endl;cout << Max(5.1, 8.3) << endl;cout << Max("Red", "Blue") << endl;

}

Consider the three global functions above. Each function performs the identical task of calculating the maximum of two types (int, double or string). Clearly, these functions differ only in terms of the data types used. The code for each function is identical.

Such functions are ideal candidates for being rewritten as a single parameterised template function.

Page 6: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 6

Copyright ©1994-2010 CRS Enterprises 6

Template Functions

template <typename T>T Max(T a, T b){

if (a > b)return a;

elsereturn b;

}

template <typename T>T Max(T a, T b){

if (a > b)return a;

elsereturn b;

}

• Parameters can be classes or built in types

– use class or typename

int main(){

string s1 = "Red";string s2 = "Blue";cout << Max(5, 8) << endl;cout << Max(5.1, 8.3) << endl;cout << Max(s1, s2) << endl;

}

int main(){

string s1 = "Red";string s2 = "Blue";cout << Max(5, 8) << endl;cout << Max(5.1, 8.3) << endl;cout << Max(s1, s2) << endl;

}

calls template with T = intcalls template with T = doublecalls template with T = string

The parameterized function template is written above. Note the use of the template keyword to introduce the function. The template parameters are enclosed in angled brackets (to distinguish them from function parameters).

Templates are instantiated by calling the template function and omitting the angled brackets. The call

Max(5, 8)

will instantiate the template for ints, whereas

Max(5.1, 8.3)

Max(s1, s2)

will instantiate the template for doubles and strings respectively.

Note that convention demands you use a single upper case letter for the template parameter.

Page 7: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 7

Copyright ©1994-2010 CRS Enterprises 7

Ambiguities• Compiler must be able to uniquely determine paramet er

types– does T = int or double?

• These ambiguities rarely arise– types too similar

template <typename T>T Max(T a, T b){

if (a > b)return a;

elsereturn b;

}

template <typename T>T Max(T a, T b){

if (a > b)return a;

elsereturn b;

}

double x = Max(5.1, 8);double x = Max(5.1, 8);

double x = Max(8, 5.1);double x = Max(8, 5.1);

double x = Max(5.1, 8);double x = Max(5.1, 8);

double x = Max(8, 5.1);double x = Max(8, 5.1);

With a template function, the compiler must be able to uniquely determine each parameter type from the template call. For example, in the function call

Max(5.1,8)

the template parameter T could be either an int or a double. Ambiguities like this are not allowed and the template call will fail. Fortunately, when templates are used with classes such ambiguities rarely arise.

Page 8: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 8

Copyright ©1994-2010 CRS Enterprises 8

Multiple Template Parameters

template <typename T1, typename T2>double Max(T1 a, T2 b){

if (a > b)return a;

elsereturn b;

}

template <typename T1, typename T2>double Max(T1 a, T2 b){

if (a > b)return a;

elsereturn b;

}

• Templates can have many parameters– compiler must be able to deduce types

double x = Max(5.1, 8);double y = Max(8, 5.1);

double x = Max(5.1, 8);double y = Max(8, 5.1);

T1=double, T2=int

T1=int, T2=double

Templates can have many parameters. In this example the template assumes there are two different types being passed to Max. In all cases the compiler must be able to deduce these types otherwise the template call will fail.

Although from a syntactic viewpoint the above code compiles and runs without a problem, you should consider the semantics of the code carefully. In this example we are finding the larger of two different types and although this makes sense for an int-double combination, does it make sense for doubles and strings?

Page 9: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 9

Copyright ©1994-2010 CRS Enterprises 9

Ambiguous Return Types

template <typename L, typename R, typename RET>RET Max(L a, R b){

if (a > b)return a;

elsereturn b;

}

template <typename L, typename R, typename RET>RET Max(L a, R b){

if (a > b)return a;

elsereturn b;

}

• Return value not considered deterministic– complier can't deduce RET

double x = Max(5.1, 8);double y = Max(8, 5.1);

double x = Max(5.1, 8);double y = Max(8, 5.1);

You might be tempted to assume that a template's return type can be deduced from the context in which the template is used. Unfortunately, C++ compilers don't use the context (i.e. the type on the left hand side of the assignment) during template instantiation and therefore the above attempt will fail to compile.

Page 10: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 10

Copyright ©1994-2010 CRS Enterprises 10

Ambiguous Parameters

int main(){

string s = Max("Red", "Blue");}

int main(){

string s = Max("Red", "Blue");}

• Compiler deduces parameters– according to language definitions

• Easy to confuse const char* and string– double quotes implies const char*

template <typename T>T Max(T a, T b){

if (a > b)return a;

elsereturn b;

}

template <typename T>T Max(T a, T b){

if (a > b)return a;

elsereturn b;

}

will compare pointers

The compiler will always use language definitions to determine template parameter types. Sometimes this can be a little confusing. For example, if you pass two "strings" to Max using double quotes, the compiler will deduce that the parameters are by definition char* and not string. What is worse is that the Max function will find the larger of the two pointers and not compare the strings. Definitely not what you wanted!

Page 11: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 11

Copyright ©1994-2010 CRS Enterprises 11

Unambiguous Notation

int main(){

string s1 = Max<string>("Red", "Blue");

string s2 = Max(String("Red"), String("Blue"));}

int main(){

string s1 = Max<string>("Red", "Blue");

string s2 = Max(String("Red"), String("Blue"));}

• Can always specify template parameters in the call– or use a cast

template <typename T>T Max(T a, T b){

if (a > b)return a;

elsereturn b;

}

template <typename T>T Max(T a, T b){

if (a > b)return a;

elsereturn b;

}

messy

recommended

To avoid ambiguities on parameter type deduction you can state the type explicitly, as in

string s1 = Max<string>("Red", "Blue");

or if you prefer, use a cast

string s2 = Max(String("Red"), String("Blue"));

Usually the former notation is clearer and therefore recommended.

Page 12: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 12

Copyright ©1994-2010 CRS Enterprises 12

Max<string>("Red", "Blue");

Max("Red", "Blue");

Max<string>("Red", "Blue");

Max("Red", "Blue");

Special Cases

template <typename T>T Max(T a, T b){

if (a > b)return a;

elsereturn b;

}

const char* Max(const char* a, const char* b){

if (strcmp(a,b) > 0)return a;

elsereturn b;

}

template <typename T>T Max(T a, T b){

if (a > b)return a;

elsereturn b;

}

const char* Max(const char* a, const char* b){

if (strcmp(a,b) > 0)return a;

elsereturn b;

}

• special cases can be defined

– compiler always prefers a non template function

– exact parameter matches preferred to casting

In many situations you would like to use a generic algorithm, but special cases exist.

No problem. Define a template for the generic case and provide an explicit function (specialization) for the special case. The compiler will always select non-template functions if each parameter exactly matches the function signature.

In cases where the parameter types don't quite match, the compiler will attempt to cast to resolve the ambiguity. This leads to four cases

non-template function with exact parameter matches

template function with exact parameter matches

non-template function requiring casts to fix parameter matches

template function requiring casts to fix parameter matches

The compiler will attempt to match function calls by working down the above list.

Page 13: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 13

Copyright ©1994-2010 CRS Enterprises 13

Introduction to Templates

Template Functions

Template Classes

Specialization

Template MetaPrograms

Traits

Template Template Parameters

Page 14: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 14

Copyright ©1994-2010 CRS Enterprises 14

Generic Classes

class ArrayOfInts{private:

int array[3];public:

ArrayOfInts(int);void Print( );

};

class ArrayOfDoubles{private:

double array[3];public:

ArrayOfDoubles(double);void Print( );

};

class ArrayOf Ints{private:

int array[3];public:

ArrayOf Ints(int );void Print( );

};

class ArrayOf Double s{private:

double array[3];public:

ArrayOf Double s(double );void Print( );

};

• Similar Classes– ready to be converted to templates

int main( ){

ArrayOfInts a(3);ArrayOfDoubles b(5.5);

}

int main( ){

ArrayOf Ints a(3);ArrayOf Double s b(5.5);

}

• identify types– that can be made generic

Consider the two classes ArrayOfInts and ArrayOfDoubles shown above. These classes have a great deal in common and are suitable candidates for being converted into a class template.

However, with class templates we have more work to accomplish than with function templates. Not only do we need to parameterize the class definitions, but we need to write templates for all common methods, including constructors.

Page 15: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 15

Copyright ©1994-2010 CRS Enterprises 15

Converting to Templates• Create Templates for

– class definition– each member function

• Parameters can be classes or built in types

– use class or typename

template <class T>class Array{private:

T array[3];public:

Array(T);void Print( );

};

template <class T>class Array{private:

T array[3];public:

Array( T);void Print( );

};

template <class T>Array<T>::Array(T x0){

for (int i = 0; i < 3; i++)array[i] = x0;

}

template <class T>void Array<T>::Print( ){

for (int i = 0; i < 3; i++)cout << array[i] << '\t';

cout << endl;}

template <class T>Array< T>::Array( T x0){

for (int i = 0; i < 3; i++)array[i] = x0;

}

template <class T>void Array< T>::Print( ){

for (int i = 0; i < 3; i++)cout << array[i] << '\t';

cout << endl;}

Converting the two classes ArrayOfInts and ArrayOfDoubles to templates is straightforward. Note that a template is required not only for the class definition, but also for each member function.

The template parameter does not have to be a class, despite the class keyword. In fact the template parameter can be either a class or a built in type. You can use the typename keyword in place of class; the two are synonymous.

Page 16: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 16

Copyright ©1994-2010 CRS Enterprises 16

Instantiating Templates• Template instantiation

– compiler instantiates a new class for each call– linker removes duplicates

int main( ){

Date newYear(1, 1, 2000);

Array<int> a(8);Array<double> b(8.888);Array<Date> c(newYear);

a.Print( );b.Print( );c.Print( );

}

int main( ){

Date newYear(1, 1, 2000);

Array<int> a(8);Array<double> b(8.888);Array<Date> c(newYear);

a.Print( );b.Print( );c.Print( );

}

template <typename T>class Array { ... }

template < typename T>Array<T>::Array(T x0) { ... }

template < typename T>void Array<T>::Print( ) { ... }

template <typename T>class Array { ... }

template < typename T>Array<T>::Array(T x0) { ... }

template < typename T>void Array<T>::Print( ) { ... }

All that remains is to instantiate the templates in a calling program. Types are passed inside angle brackets

Array<int> a(8);

Array<double> b(8.888);

Array<Date> c(newYear);

The compiler instantiates a separate class for each of these calls, along with the associated member functions. In the case where a template is instantiated in several compilation modules this will lead to duplicate class definitions; the linker will remove any unnecessary code. This scheme is used by the majority of compiler/linker systems, other systems handle template instantiation differently from above.

Page 17: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 17

Copyright ©1994-2010 CRS Enterprises 17

Template Parameters• 3 Categories of Template Parameters

– Typenames– a user defined type (e.g. Date)– built in type (e.g. int)

– Values– the value of a type (e.g. 3)

– Template– templates can accept other templates as parameters– beware syntax pitfall with double > >

template <typename T, template <typename U> >// class definition that uses T and U

template <typename T, template <typename U> >// class definition that uses T and U

note the space in > >

Templates can take any number of parameters and each parameter can come from one of three categories.

Typename

We have already seen the use of typenames as template parameters.

Value

Parameters can be simple values, the same as in function calls.

Template

Templates can accept other templates as parameters. This can lead to complex and intriguing designs. Much of the power of C++'s template mechanism lies in the use of these so called template template parameters. Be careful to leave a space between the closing > of the two templates; the compiler assumes >> is the right shift operator.

Page 18: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 18

Copyright ©1994-2010 CRS Enterprises 18

Using Values as Parameters• template Value parameters

– value must be known at compile time

int main( ){

Date newYear(1, 1, 2000);

Array<int, 3> a(8);Array<double, 5> b(8.888);Array<Date, 4> c(newYear);

a.Print( );b.Print( );c.Print( );

}

int main( ){

Date newYear(1, 1, 2000);

Array<int, 3> a(8);Array<double, 5> b(8.888);Array<Date, 4> c(newYear);

a.Print( );b.Print( );c.Print( );

}

template <typename T, int SIZE>class Array{private:

T array[SIZE];public:

Array(T);void Print( );

};

template < typename T, int SIZE>Array<T , SIZE>::Array(T x0){

for (int i = 0; i < SIZE; i++)array[i] = x0;

}

template < typename T, int SIZE>void Array<T , SIZE >::Print( ){

for (int i = 0; i < SIZE; i++)cout << array[i] << '\t';

cout << endl;}

template <typename T, int SIZE>class Array{private:

T array[ SIZE];public:

Array( T);void Print( );

};

template < typename T, int SIZE>Array<T , SIZE>::Array(T x0){

for (int i = 0; i < SIZE; i++)array[i] = x0;

}

template < typename T, int SIZE>void Array<T , SIZE >::Print( ){

for (int i = 0; i < SIZE; i++)cout << array[i] << '\t';

cout << endl;}

As mentioned previously, template parameters are not restricted to typenames. In the example above, the size of the array is parameterised in the template

template <typename T, int SIZE>

The template defines an array of type T with a SIZE specified at compile time. You can see why templates are so popular - with minimal effort we have created an extremely powerful set of classes!

Note that the class name is becoming a little complicated. The constructor

template <typename T, int SIZE>

Array<T , SIZE>::Array(T x0)

refers to the class

Array<T , SIZE>

Page 19: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 19

Copyright ©1994-2010 CRS Enterprises 19

Default Parameters• default parameters

– similar to functions

int main( ){

Array<int, 6> a(1);Array<int> b(2);Array<> c(3);...

}

int main( ){

Array<int, 6> a(1);Array<int> b(2);Array<> c(3);...

}

template <typename T = int , int SIZE = 6>class Array{private:

T array[SIZE];public:

Array(T);void Print( );

};

template < typename T, int SIZE>Array<T , SIZE>::Array(T x0){

for (int i = 0; i < SIZE; i++)array[i] = x0;

}

template < typename T, int SIZE>void Array<T , SIZE >::Print( ){

for (int i = 0; i < SIZE; i++)cout << array[i] << '\t';

cout << endl;}

template <typename T = int , int SIZE = 6>class Array{private:

T array[SIZE];public:

Array(T);void Print( );

};

template < typename T, int SIZE>Array<T , SIZE>::Array(T x0){

for (int i = 0; i < SIZE; i++)array[i] = x0;

}

template < typename T, int SIZE>void Array<T , SIZE >::Print( ){

for (int i = 0; i < SIZE; i++)cout << array[i] << '\t';

cout << endl;}

template <typename T = int , int SIZE = 6>class Array{ ... };

template <typename T = int , int SIZE = 6>class Array{ ... };

A nice addition to templates is the ability to supply default parameters. This works in much the same way as with functions.

More advanced use of templates often involves defining several template parameters, with many of the parameters providing specialist behavior. It is really convenient if most of the template parameters can be defaulted to sensible values; then the casual user needs only to supply the essential parameters and let the template decide on default values for the rest. The specialist user still can customize the template by supplying every parameter.

Page 20: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 20

Copyright ©1994-2010 CRS Enterprises 20

Introduction to Templates

Template Functions

Template Classes

Specialization

Template MetaPrograms

Traits

Template Template Parameters

Page 21: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 21

Copyright ©1994-2010 CRS Enterprises 21

Template Specialization• Partial Specialization

– specialized version of template– only called for a subset of types– e.g. pointer types

• Full Specialization– specialized version of template

– only called for a defined type

• Both specializations ...– generic template is still required

– but only needs to be declared– not necessary to define if not used

Advanced techniques with templates rely on template specialization. You can define a generic template as per the previous slides, but then provide special cases of the template, or specializations, with a completely different code base.

There are two forms of template specialization

partial specialization

With partial specialization, a subset of possible template parameters will use the specialized template, but everything else will use the generic template. For example you can define a template that takes a typename T with a specialization for all pointer types T*.

full specialization

This is similar to partial specialization, except the special case must be uniquely defined. For example you can define a template that takes a typename T with a specialization for the case where T is an int.

It should be noted that the generic template is still required, even if you only want to instantiate the specialized types. If you never intend to instantiate the generic template, you are allowed to merely declare the template and not provide any implementation.

Page 22: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 22

Copyright ©1994-2010 CRS Enterprises 22

Full Specialization• Specialize on type

– generic template for T– specialization for int

int main(){

collection<string> list1;collection<int> list2;collection<bool> list3;

list1.f1();list2.f2();list3.f1();

}

int main(){

collection<string> list1;collection<int> list2;collection<bool> list3;

list1.f1();list2.f2();list3.f1();

}

// the generic templatetemplate <typename T>class collection{public:

void f1() {}void f2() {}void f3() {}

};

// specialization for booltemplate <>class collection<bool>{public:

void f1() {}void f2() {}void f3() {}

};

// the generic templatetemplate <typename T>class collection{public:

void f1() {}void f2() {}void f3() {}

};

// specialization for booltemplate <>class collection< bool >{public:

void f1() {}void f2() {}void f3() {}

};

This example shows how full specialization of templates works. The generic template is defined, followed by the specialization. The specialization parameter is added to the class definition

class collection<bool>

Note the template clause has no parameters defined

template <>

Typically, full specializations will be provided for a number of types. All specializations must follow the declaration of the generic template.

As before, the code base for the generic and full specialization are unrelated. If you only intend to use the fully specialized templates, the generic template must still be declared as

// the generic template

template <typename T> class collection;

Page 23: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 23

Copyright ©1994-2010 CRS Enterprises 23

Partial Specialization• Specialize on pointer types

– generic template for T– specialization for T*

int main(){

collection<string> list1;collection<double> list2;collection<int*> list3;

list1.f1();list2.f2();list3.f1();

}

int main(){

collection<string> list1;collection<double> list2;collection<int*> list3;

list1.f1();list2.f2();list3.f1();

}

// the generic templatetemplate <typename T>class collection{public:

void f1() { ... }void f2() { ... }void f3() { ... }

};

// partial specialization for pointerstemplate <typename T>class collection<T*>{public:

void f1() { ... }void f2() { ... }void f3() { ... }

};

// the generic templatetemplate <typename T>class collection{public:

void f1() { ... }void f2() { ... }void f3() { ... }

};

// partial specialization for pointerstemplate <typename T>class collection< T*>{public:

void f1() { ... }void f2() { ... }void f3() { ... }

};

This example shows how partial specialization of templates works. The generic template is defined, followed by the specialization. The specialization parameter is added to the class definition

class collection<T*>

The code base for the generic template and for the partial specializations are unrelated. If you only intend to use the specialization templates, the generic template must still be declared, but not defined, as in

// the generic template

template <typename T> class collection;

Page 24: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 24

Copyright ©1994-2010 CRS Enterprises 24

Introduction to Templates

Template Functions

Template Classes

Specialization

Template MetaPrograms

Traits

Template Template Parameters

Page 25: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 25

Copyright ©1994-2010 CRS Enterprises 25

Template Meta-Programs• Program 'runs' at compile time

– recursive algorithms– use templates

– generic template defines algorithm– template specialization to end the recursion

• Performance– meta-programs can gain a big performance gain over traditional

runtime programs

• Examples– Factorial– Fibonacci– Bubble Sort

Template meta-programs are specialized programs that are computed during the compilation. These programs make extensive use of templates and recursive algorithms. Compile time programs are analogous to the #define macro expansions familiar from C, and like their C counterpart, these meta-programs can give a significant performance boost to their runtime equivalents.

We will investigate three typical examples

Factorial

Fibonacci

Bubble Sort

Page 26: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 26

Copyright ©1994-2010 CRS Enterprises 26

Factorial Meta-Program• Recursion

– Generic template for general case – F(N) = N * F(N-1)

– Full specialization for special case– F(1) = 1

template<int N>class Factorial {public:

enum { value = N * Factorial<N-1>::value };};

template<>class Factorial<1>{public:

enum { value = 1 };};

template<int N>class Factorial {public:

enum { value = N * Factorial<N-1>::value };};

template<>class Factorial<1>{public:

enum { value = 1 };};

int main(){

int x;x = Factorial<6>::value;

}

int main(){

int x;x = Factorial<6>::value;

}

All meta-programs are computed at compile time and use the same basic principles. Obviously, ordinary variables cannot be used in a compile time program, so the alternative is to use templates with recursion. It turns out that enums are the only entity available for performing calculations at compile time with the implication that meta-programs are restricted to integer arithmetic.

In the above example the generic template defines an enum value in terms of an enum value from a related template using a recursive relation

Factorial<N>::value = N * Factorial<N-1>::value

The recursion is broken by a fully specialized template

Factorial<1>::value = 1

To test the meta-program we can assign the compile time constant

Factorial<6>::value

to x and either inspect the variable at runtime in a debugger or add a print statement.

Page 27: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 27

Copyright ©1994-2010 CRS Enterprises 27

Fibonacci Meta-Program• Recursion

– Generic template for general case – F(N) = F(N-1) + F(N-2)

– Full specialization for special case– F(2) = 1– F(1) = 1

template<>class Fibonacci<1>{public:

enum { value = 1 };};

template<>class Fibonacci<1>{public:

enum { value = 1 };};

template<int N>class Fibonacci {public:

enum { value = Fibonacci<N-1>::value + Fibonacci<N- 2>::value };};

template<int N>class Fibonacci {public:

enum { value = Fibonacci<N-1>::value + Fibonacci<N- 2>::value };};

template<>class Fibonacci<2>{public:

enum { value = 1 };};

template<>class Fibonacci<2>{public:

enum { value = 1 };};

int main(){

int x[4];x[0] = Fibonacci<1>::value;x[1] = Fibonacci<2>::value;x[2] = Fibonacci<3>::value;x[3] = Fibonacci<4>::value;

}

int main(){

int x[4];x[0] = Fibonacci<1>::value;x[1] = Fibonacci<2>::value;x[2] = Fibonacci<3>::value;x[3] = Fibonacci<4>::value;

}

This is a slightly more complicated meta-program. This time the generic algorithm is defined as

Fibonacci<N>::value = Fibonacci<N-1>::value + Fibonacci<N-2>::value

The recursion is broken by two fully specialized templates

Fibonacci<1>::value = 1

Fibonacci<2>::value = 1

Page 28: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 28

Copyright ©1994-2010 CRS Enterprises 28

Introduction to Templates

Template Functions

Template Classes

Specialization

Template MetaPrograms

Traits

Template Template Parameters

Page 29: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 29

Copyright ©1994-2010 CRS Enterprises 29

A Problem

template <typename L, typename R, typename RET>RET Max(L a, R b){

if (a > b)return a;

elsereturn b;

}

template <typename L, typename R, typename RET>RET Max(L a, R b){

if (a > b)return a;

elsereturn b;

}

• Return value not considered deterministic– complier can't deduce RET

double x = Max(5.1, 8);double y = Max(8, 5.1);float f1 = Max(5.1F, 8);float f2 = Max(8, 5.1F

double x = Max(5.1, 8);double y = Max(8, 5.1);float f1 = Max(5.1F, 8);float f2 = Max(8, 5.1F

The compiler will attempt to determine the actual types of template parameters, but in some cases this is not possible. In the example above, the return time is non deterministic, due to the underlying design of the C language, where return can be ignored. In these cases a new approach is required : Traits.

Page 30: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 30

Copyright ©1994-2010 CRS Enterprises 30

Using Specialization

template <typename L, typename R>typename promote_trait<L,R>::T_promote Max(L a, R b){

if (a > b)return a;

elsereturn b;

}

template <typename L, typename R>typename promote_trait<L,R>::T_promote Max(L a, R b){

if (a > b)return a;

elsereturn b;

}

• Define each special case– Max(int, float) returns float– Max(int, double) returns double– Max(float, int) returns float– Max(double, int) returns double

define as a specialized template

In the template above the return type for Max is a parameterized templated type. This means you can determine the return type elsewhere from the two parameter types L and R using the promote_trait template.

Page 31: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 31

Copyright ©1994-2010 CRS Enterprises 31

The promote_trait Template• Generic case ..

– must be defined,– but not used

• Full Specialization– for each case– does the real work

// generic casetemplate<class A, class B>class promote_trait {public:

typedef void T_promote;};

// generic casetemplate<class A, class B>class promote_trait {public:

typedef void T_promote;};

template<>class promote_trait<int, double> {public:typedef double T_promote;};

template<>class promote_trait <int, double> {public:typedef double T_promote;}; template<>

class promote_trait<double, int> {public:typedef double T_promote;};

template<>class promote_trait <double, int> {public:typedef double T_promote;};

Templates are always defined for the generic case and then special cases can be defined using the appropriated termed specialization templates. In the example above, the specializations are defined for the cases where the template parameters A and B are either int and double or vice versa.

The specializations work by defining a typedef T_promote. Clearly each specialization is free to define this typedef differently, but in this case both specializations define the typedef as double.

Note these are full specializations: A and B are fully determined. Traits can also employ partial specializations.

Finally, note that the generic case must be defined, but often (as in this case) the generic case is not actually used.

Page 32: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 32

Copyright ©1994-2010 CRS Enterprises 32

Extended type traits information• Type traits allow us to gain information about a ty pe

when meta-programming (templates):– Primary traits

– Allow you to find out if a type belongs to one of t he basic categories

– Composite traits– Are convenient combinations of primary traits

– Type properties– More fine-grained information about a type

– Type relationships– Comparing two types

Traits can also be used gain information about a type when meta-programming with templates. For example you might wish to determine if the type is void, or o pointer type, or even a derived type. See below for some of the multitude of possibilities.

Page 33: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 33

Copyright ©1994-2010 CRS Enterprises 33

Primary traits

Template

is_voidis_integralis_floating_pointis_arrayis_enumis_unionis_classis_functionis_lvalue_referenceis_rvalue_referenceis_member_object_pointeris_member_function_pointeris_pointer

Template

is_voidis_integralis_floating_pointis_arrayis_enumis_unionis_classis_functionis_lvalue_referenceis_rvalue_referenceis_member_object_pointeris_member_function_pointeris_pointer

::value is true if the argument is...

voidan integral typea floating-point typean array typean enumeration typea union typea class type (but not union type)a function typean lvalue referencean rvalue referencea pointer to a non-static member objecta pointer to a non-static member functiona pointer type (but not a pointer to a

non-static member object or function)

::value is true if the argument is...

voidan integral typea floating-point typean array typean enumeration typea union typea class type (but not union type)a function typean lvalue referencean rvalue referencea pointer to a non-static member objecta pointer to a non-static member functiona pointer type (but not a pointer to a

non-static member object or function)

The classification traits describe the C++ taxonomy of types. These traits are grouped into two broad categories: primary and secondary. The primary traits identify the leaves of the taxonomy tree. Every type that can be created in C++ fits into one and only one of the primary categories.

The above Primary traits can be used with other templates in a similar way to our previous example.

Page 34: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 34

Copyright ©1994-2010 CRS Enterprises 34

Composite traits

Template

is_referenceis_arithmeticis_fundamentalis_objectis_scalaris_compoundis_member_pointer

Template

is_referenceis_arithmeticis_fundamentalis_objectis_scalaris_compoundis_member_pointer

::value is true if the argument is...

is_lvalue_reference || is_rvalue_referenceis_integral || is_floating_pointis_arithmetic || is_void!is_function && !is_reference && !is_voidis_arithmetic || is_enum || is_pointer || is_member_pointer!is_fundamentalis_member_object_pointer || is_member_function_pointer

::value is true if the argument is...

is_lvalue_reference || is_rvalue_referenceis_integral || is_floating_pointis_arithmetic || is_void!is_function && !is_reference && !is_voidis_arithmetic || is_enum || is_pointer || is_member_pointer!is_fundamentalis_member_object_pointer || is_member_function_pointer

The secondary classifications represent combinations of the primary classifications (composite traits) that are useful for determining characteristics of a relatively broad range of types (e.g. is a type a scalar?).

Page 35: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 35

Copyright ©1994-2010 CRS Enterprises 35

Introduction to Templates

Template Functions

Template Classes

Specialization

Template MetaPrograms

Traits

Template Template Parameters

Page 36: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 36

Copyright ©1994-2010 CRS Enterprises 36

Template Parameters• Template parameters must be:

• 1. Types– template t1<T1, T2, T3, T4>

– where T1=int, T2=double, T3=Money, T4=Date

• 2. Values– template t2<int N, double D>

– where N=3, D=5.87 (compile time constant)

• 3. Other templates– template t3< template t1<....> >

– beware closing > > – (OK in C++11)

– extensive use of recursion

Part of the flexibility of C++ template stems from the design that parameters can be taken from three different categories. Simple templates will define their parameters in terms of other types which will be determined at template instantation time. Parameters can also be denied as actual values (not types) such as an integer, say 3 or a double with value 5.87. Such values are compile time constants.

More complex templates can be defined in terms of other templates - the so called template template parameters. Such templates make extensive use of recursion. These templates require a lot of thought in their design.

Together with specialization, template parameters provide an extremely flexible and extensible framework.

Page 37: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 37

Copyright ©1994-2010 CRS Enterprises 37

Template Template Parameters ...• Start with some ordinary templates

template <class T> struct _4ple{

T t1;T t2;T t3;T t4;

};

template <class T> struct _4ple{

T t1;T t2;T t3;T t4;

};

template <class T> struct _3ple{

T t1;T t2;T t3;

};

template <class T> struct _3ple{

T t1;T t2;T t3;

};template <class T> struct _2ple{

T t1;T t2;

};

template <class T> struct _2ple{

T t1;T t2;

};

Templates that employ template template parameters tend to be very complicated, so the above example is a little contrived. Starting with some simple templates (see above) we progress on the next slide ...

Page 38: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 38

Copyright ©1994-2010 CRS Enterprises 38

... Template Template Parameters• Use these templates as parameters to other template s

template <template<typename dummy> class T, typename S>struct builder{

T<S> u1;T<S> u2;

};

template <template<typename dummy> class T , typename S>struct builder{

T<S> u1;T<S> u2;

};

dummy name is never used

int main(){

builder<_2ple,double> m2;builder<_3ple,int> m3;builder<_4ple,string> m4;...

}

int main(){

builder< _2ple ,double> m2;builder< _3ple ,int> m3;builder< _4ple ,string> m4;...

}

Once these templates have been defined, they can be used in another template: builder. The builder template takes a template as a parameter. In the main program this template is set to _2ple, _3ple and _4ple in turn.

Note the rather awkward syntax. The inner template takes a parameter, which must be given a name (dummy), but is never actually referred to in the definition of the outer template.

Page 39: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 39

Page 40: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 40

Copyright ©1994-2010 CRS Enterprises 40

The New C++11 Standard

• Language Changes– lots of them

• Library Changes

2

This chapter investigates the Standard Template Library (STL). The STL provides an extensive set of data structures or containers and a large number of algorithms that operate on these containers.

Page 41: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 41

Copyright ©1994-2010 CRS Enterprises 41

C++ Standards

1980

1990

2000

2010

C++

ARMARM

ISOStandard

1998

ISOStandard

1998

2020

ISOStandard

2003

ISOStandard

2003ISO

Standard2011

ISOStandard

2011

C originated in the years 1969-1973, in parallel with the early development of the Unix operating system. C was written by Dennis Ritchie and Brian Kernighan and underwent many changes in its early years..

C++ was designed for the UNIX system environment by Bjarne Stroustrup as an object oriented version of C. C++ was first standardized in 1998. Before that Bjorn Stroustroup and Mary Ellis's Annotated Reference Manual (ARM) was effectively the standard. The standard had minor additions in 2003, but it was not until 2011 that a major revision took place.

Page 42: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 42

Copyright ©1994-2010 CRS Enterprises 42

Core Language Enhancements ...• Rvalue references and move constructors

– optimisation with deep copies

• Constant expressions– compile time definitions for optimizations

• More consistence syntax for initialization– of 'plain old data'

• Extern templates– inhibit generation of templates in a compilation un it

The new C++11 standard includes a number of core language enhancements.

Perhaps the most important change is the introduction of rvalue references. Rvalue references are used in move constructors to allow efficient copying of objects when one of the objects is anonymous and will be deleted as soon as the copy is completed.

The concept of compile time constants has been extended with constant expressions which allow many more compile time definitions.

In previous versions of the standard, there are many different ways to initialize, dependent upon what you are initializing. In C++1 the language syntax has been cleaned up to allow a more consistence syntax for initialization.

Other changes include the introduction of extern templates, which inhibit generation of templates in a compilation unit (generated in in an external compilation unit), thereby speeding up the compilation time.

Page 43: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 43

Copyright ©1994-2010 CRS Enterprises 43

... Core Language Enhancements• Many other language enhancements ...

– type inference– range based loop– lambda functions– alternative declarations of return types– constructors calling other constructors (as in Java )– type safe enums– >> can be template terminator– explicit now applies to operator casts (as well as CTOR cast s)– template aliases– variadic templates– new Unicode strings

Many other language enhancements have been added in the new standard. These include the topics shown above (which is nearly the complete list).

Some of the enhancements have been borrowed from functional languages (such as lambda functions) to bring C++ up to date. The enhancements will no doubt will change the look and feel of the C++ code you write.

Page 44: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 44

Copyright ©1994-2010 CRS Enterprises 44

... Core Language Enhancements• And still more ...

• Threading is now part of the language– memory model defined– implementations are library based

– e.g. Boost Threading

• Upgrades to the STL– tuples– hash tables– RegEx– Smart Pointers– Random Numbers– Metaprogramming– Type traits

Previous incarnations of the standard always assumed a single threaded model. While this was satisfactory in the nineties, with the explosion of multi-core cpus it has become essential to define a multithreaded memory model for C++. As Java has shown, this is a non trivial task and has delayed the introduction of the standard.

Therefore, threading is now part of the language with a Java like memory model defined. Implementations are library based and taken from the work done on the Boost Threading library.

Elsewhere there have been many additions to the STL, including

tuples

hash tables

RegEx

Smart Pointers

Random Numbers

Metaprogramming

Type traits

Page 45: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 45

Copyright ©1994-2010 CRS Enterprises 45

Object Initialisation• C++ 98 has several initialization notations

– some notations are restricted in their use

• Parenthesized initialization:– std::string s("hello");

• = notation:– std::string s = "hello";

• braces:– int arr[4] = {0,1,2,3};– struct tm today = {0};

• member initializers in CTORs:– struct S { int x; S(): x(0) {} };

C++ 98 has several initialization notations and some notations are restricted in their use. This has all been cleaned up in C++11. There is now a consistent application of syntax, for example, a vector can be initialized with the same syntax used to initialized a C style array.

Page 46: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 46

Copyright ©1994-2010 CRS Enterprises 46

Brace initialisation notation• In C++11 you can use any standard notation for

initialization

class Point{private:

int x = 0;int y = 0;

public: Point(int x0, int y0);

};

Point p1{0, 0};Point p2(0,0);Point p3{};Point p4;

class Point{private:

int x = 0;int y = 0;

public: Point(int x0, int y0);

};

Point p1{0, 0};Point p2(0,0);Point p3{};Point p4;

initialization of member variablesas in Java

In C++11 you can use any standard notation for initialization. Calling constructors can be achieved in several ways as shown above.

A very welcome addition has been the introduction of Java style initialization of member variables. Unfortunately this has not been extended to static members.

Page 47: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 47

Copyright ©1994-2010 CRS Enterprises 47

Container Initialisation• STL containers can be initialized like arrays

std::vector<string> vs = { "first", "second", "third"};

std::map<string, int> myMap{

{"Dijkstra", 1972}, {"Scott", 1976}, {"Wilkes", 1967}, {"Hamming", 1968}

};

std::vector<string> vs = { "first", "second", "third"};

std::map<string, int> myMap{

{"Dijkstra", 1972}, {"Scott", 1976}, {"Wilkes", 1967}, {"Hamming", 1968}

};

STL containers can now be initialized like arrays, thereby simplifying the look and fell of your STL code.

Page 48: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 48

Copyright ©1994-2010 CRS Enterprises 48

range-for statement• The range-for statement provides iteration through a

container of objects

int a[6] = { 2, 3, 5, 7, 11, 13 };

int main(){

for(int& x: a){

x = x * 10;}

}

int a[6] = { 2, 3, 5, 7, 11, 13 };

int main(){

for(int& x: a){

x = x * 10;}

}

use a reference so that you can modify array

The range-for statement provides iteration through a container of objects, with reference access to the underlying collection. This type of construct is available in many other languages.

Page 49: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 49

Copyright ©1994-2010 CRS Enterprises 49

Smart Pointers• C++11 incorporates

– shared_ptr and weak_ptr from Boost

• Replaces auto_ptr with unique_ptr– unique_ptr has move semantics– copy constructor and assignment operator explicitly deleted

– it cannot be copied, but– it can be moved using std::move – which allows unique_ptr object to transfer ownersh ip

#include <memory>std::unique_ptr<int> p2 = std::move(p1);

#include <memory>std::unique_ptr<int> p2 = std::move(p1);

Boost introduced a number of smart pointers to overcome the deficiencies of the 1998 standard. The C++11 incorporates the shared_ptr and weak_ptr from Boost and replaces auto_ptr with unique_ptr. Unique_ptr has move semantics with a copy constructor and assignment operator explicitly deleted. Therefore it cannot be copied, but it can be moved using std::move . This allows the unique_ptr to transfer ownership efficiently like its predecessor the auto_ptr.

Page 50: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 50

Copyright ©1994-2010 CRS Enterprises 50

unique_ptr ...• After years of debate, C++ standards committee deci ded

to deprecate auto_ptr• unique_ptr has same strict ownership semantics of

auto_ptr– but cleaner and safer interface– unlike auto_ptr, unique_ptr requires an explicit mo ve operation for

moving from lvalues– can't use copy syntax

– STL containers and algorithms will fail to compile code operating on unique_ptr if the container doesn't support move se mantics

– instead of leaving the bug unreported and crashing at runtime

After years of debate, C++ standards committee decided to deprecate auto_ptr, because of its unusual semantics which made it incompatible with the STL.

It has been replace by the unique_ptr. Unique_ptr has same strict ownership semantics of auto_ptr, but has a cleaner and safer interface. Unlike auto_ptr, unique_ptr requires an explicit move operation for moving from lvalues (i.e. you can't use copy syntax).

STL containers and algorithms will fail to compile code operating on unique_ptr if the container doesn't support move semantics (instead of leaving the bug unreported and crashing at runtime as was the case with auto_ptr).

Page 51: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 51

Copyright ©1994-2010 CRS Enterprises 51

... unique_ptr• Automatic cleanup of heap based objects

– exception safe

template <class T>class unique_ptr{public:

unique_ptr(unique_ptr&& u); private:

unique_ptr(const unique_ptr&);};

template <class T>class unique_ptr{public:

unique_ptr(unique_ptr&& u); private:

unique_ptr(const unique_ptr&);};

copy CTOR forlvalues

copy CTOR forlvalues

move CTOR forrvalues

move CTOR forrvalues

vector<unique_ptr<Point>>::iterator i;vector<unique_ptr<Point>> v;v.reserve(3);v.push_back(std::unique_ptr<Point>(new Point(3, 4)));v.push_back(std::unique_ptr<Point>(new Point(5, 3)));v.push_back(std::unique_ptr<Point>(new Point(7, 2)));

vector<unique_ptr<Point>>::iterator i;vector<unique_ptr<Point>> v;v.reserve(3);v.push_back(std::unique_ptr<Point>(new Point(3, 4)));v.push_back(std::unique_ptr<Point>(new Point(5, 3)));v.push_back(std::unique_ptr<Point>(new Point(7, 2)));

Here is an example using the unique pointer with a vector. Note the copy constructor is private (it could have been marked as deleted using the new syntax discussed previously) to prevent copying.

The unique_ptr support the handle body design pattern. The unique_ptr acts as the handle for heap based objects. When the unique_ptr goes out of scope it automatically calls the destructor (deletes) its body. This ensure proper cleanup of heap based objects in an exception safe manner.

Page 52: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 52

Copyright ©1994-2010 CRS Enterprises 52

String s3(s1 + s2)String s3(s1 + s2)

R-Value Refs (Move Semantics)• Move problem

– call by value invokes copy CTOR– inefficient if deep copies of temporaries are invol ved– more efficient to use move semantics

• Normally a temporary (deep copy) will be created to perform the addition

– which is immediately destroyed– better to swap pointers (move semantics)

In C++03 temporaries (rvalues) were intended to be immutable and were considered to be indistinguishable from const T& types. However, in some cases, it would have been helpful to modify temporaries for efficiency reasons. This has been addressed in C++11; temporaries are permitted to be modified after they are initialized, for the purpose of allowing "move semantics".

A chronic performance problem with C++03 is the costly and unnecessary deep copies that can happen implicitly when objects are passed by value. In C++11, a "move constructor" can be defined to overcome theses shortcomings.

Page 53: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 53

Copyright ©1994-2010 CRS Enterprises 53

class String {String(const String& old) {

cout << "ref CTOR" << endl;text = new char[strlen(old.text) + 1];strcpy(text, old.text);

}String(String&& temp) noexcept {

cout << "rref CTOR" << endl;text = temp.text;temp.text = 0;

}}

class String {String(const String& old) {

cout << "ref CTOR" << endl;text = new char[strlen(old.text) + 1];strcpy(text, old.text);

}String(String&& temp) noexcept {

cout << "rref CTOR" << endl;text = temp.text;temp.text = 0;

}}

Move Constructors• Classes can now define move constructors

– used instead of copy constructors when temporaries (rvalue references) are involved

– use noexcept to guarantee no exceptions are thrown– requirement if using the STL

why not just swap pointersto avoid deep copying

when dealing with temporaries

move CTOR

Classes can now define move constructors that are invoked instead of copy constructors when temporaries (rvalue references) are involved. Make sure you use noexcept to guarantee no exceptions are thrown when dealing with the STL or copy constructors will be used instead.

In this move constructor the text pointers are swapped, thereby reusing the data already allocated on the heap and avoiding an unnecessary deep copy. It is wise to nullify the text pointer on the temporary to avoid accidental use after the swap.

Page 54: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 54

Copyright ©1994-2010 CRS Enterprises 54

• Use std::move to ensure move constructor is invoked– rather than a copy constructor

unique_ptr<int> up1(new int(5));

// to transfers ownership use explicit moveunique_ptr<int> up2 = std::move (up1);

unique_ptr<int> up1(new int(5));

// to transfers ownership use explicit moveunique_ptr<int> up2 = std::move (up1);

std::move

Rvalue references are used with temporaries (unnamed objects) and cannot be used with named objects such as up1 above. In some cases it makes sense to use move semantics with named objects. The std::move function is provided solely for this purpose. Note that it is unsafe to use an object after it has taken part as the source of a move operation.

Page 55: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 55

Copyright ©1994-2010 CRS Enterprises 55

template<typename T, typename Arg>shared_ptr<T> factory(Arg arg) {

return shared_ptr<T>(new T(arg));}

template<typename T, typename Arg>shared_ptr<T> factory( Arg arg ) {

return shared_ptr<T>(new T(arg));}

Rvalue Refs (Perfect Forwarding) ...• Forwarding problem

– factory creates deep copy before forwarding to clie nt

– if we pass by reference arg can't be an r-value

template<typename T, typename Arg>shared_ptr<T> factory(Arg& arg) {

return shared_ptr<T>(new T(arg));}

template<typename T, typename Arg>shared_ptr<T> factory( Arg& arg ) {

return shared_ptr<T>(new T(arg));}

factory<X>(func()); // error if func returns by val ue factory<X>(41); // error

factory<X>(func()); // error if func returns by val ue factory<X>(41); // error

The other problem besides move semantics that rvalue references were designed to solve is the perfect forwarding problem. Consider the following simple factory function above.

The intent is to forward arg from the factory to T's constructor. Ideally, as far as arg is concerned, everything should behave just as if the factory function weren't there and the constructor were called directly in the client code: perfect forwarding.

Unfortunately, the code introduces an extra call by value and calling by reference doesn't help because we can't use rvalue references on non temporaries.

Page 56: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 56

Copyright ©1994-2010 CRS Enterprises 56

... Rvalue Refs (Perfect Forwarding)• Use Rvalue references

– Arg&& arg

template<typename T, typename Arg> shared_ptr<T> factory(Arg&& arg) {

return shared_ptr<T>(new T(std::forward<Arg>(arg))) ; }

template<typename T, typename Arg> shared_ptr<T> factory( Arg&& arg) {

return shared_ptr<T>(new T( std::forward<Arg>(arg) )); }

The above problems can be avoided using the newly introduced std::forward function coupled with passing arg by rvalue reference.

Page 57: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 57

Copyright ©1994-2010 CRS Enterprises 57

Type Inference• decltype

– copies type

• auto– infers the type

int x;

// define a variable with the same type as xdecltype(x) y;

int x;

// define a variable with the same type as xdecltype(x) y;

// int (*fp)(int, int) = &f;auto fp = &f;result = fp(10, 20);

// int (*fp)(int, int) = &f;auto fp = &f;result = fp(10, 20);

int f(int a, int b){

return a + b;}

int f(int a, int b){

return a + b;}

In previous versions of the standard, the type of a variable must be explicitly specified in order to use it. However, with the advent of template types and template metaprogramming techniques, the type of something, may not be easily expressed. Therefore, storing intermediates in variables is difficult, possibly requiring knowledge of the internals of a particular metaprogramming library.

The auto keyword (has been rebranded) to allow the compiler to deduce a type.

The decltype keyword copies the type of a variable (possibly unknown by the programmer).

Page 58: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 58

Copyright ©1994-2010 CRS Enterprises 58

Lambda Functions ...• creates a function inline

– can be used wherever an expression can be used

auto fp =[ ](int x, int y) -> int{

int temp = x + y;return temp;

};

auto fp =[ ](int x, int y) -> int{

int temp = x + y;return temp;

};

int result = fp(10, 20);int result = fp(10, 20);

Lambda functions have been popular in other programming languages for some time. Now you can use lambdas in C++.

Lambda functions are essentially anonymous functions defined inline and assigned to a function pointer. This is a useful syntax enhancement which improves readability and hence improves maintenance. Lambda functions can be called with the application of the function call parentheses.

Page 59: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 59

Copyright ©1994-2010 CRS Enterprises 59

... Lambda Functions• lambdas support closures

vector<int> mylist = { 2, 3, 5, 7, 11, 13, 17, 19 } ;int total = 0;

for_each( mylist.begin(),mylist.end(),

[&total] (int x) -> int{

total += x;return total;

});

vector<int> mylist = { 2, 3, 5, 7, 11, 13, 17, 19 } ;int total = 0;

for_each( mylist.begin(),mylist.end(),

[&total] (int x) -> int{

total += x;return total;

});

closure on reference to total

closure on reference to total

It is important to realize that lambda functions support closures. This means that they understand their environment, i.e. they can use local variables that are in scope, but defined external to the function.

Closures are captured when the lambda code is invoked (i.e. assigned to a function pointer), but the lambda may be called at a later time. In the meantime some of the local variables may have gone out of scope (the function pointer may have been copied to another stack frame). In such cases the compiler will ensure the closure is preserved, possibly by copying the stack frame to a private area on the heap.

Page 60: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 60

Copyright ©1994-2010 CRS Enterprises 60

enum class E : unsigned long { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U };

void f(enum class E x){

// conversion to int not allowedcout << x << endl;

// conversion from int not allowedx = 1;

}

int main(){

f(E::E1);f(E::E2);f(E::Ebig);

}

enum class E : unsigned long { E1 = 1, E2 = 2, Ebig = 0xFFFFFF F0U };

void f( enum class E x){

// conversion to int not allowedcout << x << endl;

// conversion from int not allowedx = 1;

}

int main(){

f(E::E1);f(E::E2);f(E::Ebig);

}

Type Safe enums

define underlying integral type

old C++ enum still availableold C++ enum still available

Enum classes provide strongly-typed enumerations.

In C++03, enumerations are not type-safe. They are effectively integers, even when the enumeration types are distinct. This allows the comparison between two enum values of different enumeration types. The only safety that C++03 provides is that an integer or a value of one enum type does not convert implicitly to another enum type. Additionally, the underlying integral type is implementation-defined; code that depends on the size of the enumeration is therefore non-portable. Lastly, enumeration values are scoped to the enclosingscope. Thus, it is not possible for two separate enumerations to have matching member names.

C++11 allows a special classification of enumeration that has none of these issues. The enumeration is type-safe. Enum class values are not implicitly converted to integers; therefore, they cannot be compared to integers either. The underlying type of enum classes is always known. The default type is int, this can be overridden to a different integral type.

Page 61: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 61

Copyright ©1994-2010 CRS Enterprises 61

long long type• allows 64 bit integral types

– signed, unsigned

int main(){

unsigned long long x = 1;

for(int i = 0; i < 64; i++){

cout << i << ":" << x << endl;x = x * 2;

}}

int main(){

unsigned long long x = 1;

for(int i = 0; i < 64; i++){

cout << i << ":" << x << endl;x = x * 2;

}}

Previously the largest integral type was long int. It is guaranteed to have at least as many usable bits as int and was often defined as 64 bits. However this wasn't guaranteed. The new long long type is guaranteed to be at least as large as a long int, and have no fewer than 64 bits.

Page 62: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 62

Copyright ©1994-2010 CRS Enterprises 62

not allowed

Alternate Function Syntax• Return types are specified before function definiti on

– can cause problems because of single pass compiler

• Alternate syntax now available:

template< typename L, typename R>Ret add(const L &lhs, const R &rhs) {

return lhs + rhs;} //Ret must be the type of lhs+rhs

template< typename L, typename R>Ret add(const L &lhs, const R &rhs) {

return lhs + rhs;} //Ret must be the type of lhs+rhs

template< typename L, typename R>auto add(const L &lhs, const R &rhs) -> decltype(lhs+rhs){

return lhs + rhs;}

template< typename L, typename R>auto add(const L &lhs, const R &rhs) -> decltype(lhs+rhs){

return lhs + rhs;}

As C++ has evolved, it has exposed a number of limitations with C, particularly with regard to function declarations. For example, the new decltype keyword can compute the return type of a function based on its input parameters. However, return types are declared before input types and this prevents such constructs being used. To circumvent this problem C++11 has introduced a trailing return type syntax as shown above.

Page 63: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 63

Copyright ©1994-2010 CRS Enterprises 63

Controlling Default Methods ...• C++ defines default class methods

– destructor – default constructor – copy constructor – copy assignment operator =

• ... and global operators– sequence operator , – address-of operator & – indirection operator * – member access operator -> – member indirection operator ->* – free-store allocation operator new – free-store deallocation operator delete

You now have control over the

generation of these methods

You now have control over the

generation of these methods

Until now, the compiler will automatically generate several member functions for any class you write. This is usually beneficial, but occasionally this can be a nuisance (e.g. to prevent copying). In fact it is surprising just how many methods (see above) are created by default.

In C++11 you now have control over which default methods are generated.

Page 64: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 64

Copyright ©1994-2010 CRS Enterprises 64

class X {public:

X() = default;X(int) { ... }X(const X&) = delete;X& operator=(const X&) = delete;

};

class X {public:

X() = default ;X(int) { ... }X(const X&) = delete ;X& operator=(const X&) = delete ;

};

... Controlling Default Methods• For example: How do create a class that doesn't all ow

copying and assignment?

class X {public:

X() {} // removed by defaultX(int) { ... }

private:X(const X&);X& operator=(const X&);

};

class X {public:

X() {} // removed by defaultX(int) { ... }

private:X(const X&);X& operator=(const X&);

};

old wayold way

new waynew way

The above example shows how to prevent the compiler generating a copy constructor and an assignment operator. For example, this would be required if you were create a lock class where copying and assignment would break the class semantics.

Page 65: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 65

Copyright ©1994-2010 CRS Enterprises 65

Variadic Template Args ...• Boost Function and Tuple classes

– really require variadic template parameters– work around involves several hacks including

– repeating code for 1, 2, 3, 4, 5 ... args– using macros

• Variadic template arguments ...– are now part of C++

Templates can take variable numbers of template parameters. This also allows the definition of type-safe variadic functions and simplify a number of library definitions. Previously C macros were used to simulate (poorly) variadic templates.

Page 66: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 66

Copyright ©1994-2010 CRS Enterprises 66

... Variadic Template Args

template <typename T>T sum(T t) {

return(t); }

template <typename T, typename ...P>T sum(T t, P ... p){

if (sizeof...(p)){

t += sum(p ...);}return(t);

}

template <typename T>T sum(T t) {

return(t); }

template <typename T, typename ...P>T sum(T t, P ... p){

if (sizeof...(p)){

t += sum(p ...);}return(t);

}

int main(){

cout << sum(1) << endl;cout << sum(1, 2) << endl;cout << sum(1, 2, 3) << endl;cout << sum(1, 2, 3, 4) << endl;cout << sum(1, 2, 3, 4, 5) << endl;

cout << sum(1.1) << endl;cout << sum(1.1, 2.2) << endl;cout << sum(1.1, 2.2, 3.3) << endl;

}

int main(){

cout << sum(1) << endl;cout << sum(1, 2) << endl;cout << sum(1, 2, 3) << endl;cout << sum(1, 2, 3, 4) << endl;cout << sum(1, 2, 3, 4, 5) << endl;

cout << sum(1.1) << endl;cout << sum(1.1, 2.2) << endl;cout << sum(1.1, 2.2, 3.3) << endl;

}

In this example, the template sum is defined as a variadic template. Here the variadic template recurses until the template has only one argument. At this point the non variadic sum template is called. Note the ellipses notation for the tail of the input parameters (P) in the variadic template.

Page 67: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 67

Page 68: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 68

Copyright ©1994-2010 CRS Enterprises 68

Standard Template Library

• Containers– vector– list– map

• Algorithms

• Iterators

3

This chapter investigates the Standard Template Library (STL). The STL provides an extensive set of data structures or containers and a large number of algorithms that operate on these containers.

Page 69: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 69

Copyright ©1994-2010 CRS Enterprises 69

Overview of the STL

ContainersContainers

AlgorithmsAlgorithms IteratorsIterators

The three components of the STL are a set of Containers, Algorithms that apply to the containers and Iterators that are used in the definition of these algorithms.

Page 70: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 70

Copyright ©1994-2010 CRS Enterprises 70

Containers• Sequence containers:

– vector– deque– list

• Container adaptors:– stack– queue– priority_queue

• Associative containers:– set– multiset– map– multimap– bitset

The STL contains sequence containers and associative containers. The standard sequence containers include vector, deque, and list. The standard associative containers are set, multiset, map, and multimap. There are also container adaptors queue, priority_queue, and stack, that are containers with specific interface, using other containers as implementation.

Page 71: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 71

Copyright ©1994-2010 CRS Enterprises 71

Algorithms• Many algorithms available

– copy– swap– transform– replace– replace_if– fill– remove– remove_if– unique– reverse– random_shuffle

A large number of algorithms to perform operations such as searching and sorting are provided in the STL, each implemented to require a certain level of iterator (and therefore will work on any container which provides an interface by iterators).

Page 72: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 72

Copyright ©1994-2010 CRS Enterprises 72

Iterators• Input and output iterators

– most limited types of iterators– only sequential input or output operations

• Forward iterators– functionality of input and output iterators– limited to traversal in one direction

• Bidirectional iterators– can iterate in both directions– all standard containers support at least bidirectio nal iterators

• Random access iterators– implement functionalities of bidirectional iterator s– can also access ranges non-sequentially

Input and output iterators are the most limited types of iterators, specialized in performing only sequential input or output operations.

Forward iterators have all the functionality of input and output iterators, although they are limited to one direction in which to iterate through a range.

Bidirectional iterators can be iterated through in both directions. All standard containers support at least bidirectional iterators types.

Random access iterators implement all the functionalities of bidirectional iterators and can also access ranges non-sequentially.

Page 73: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 73

Copyright ©1994-2010 CRS Enterprises 73

Vector

vector<string> collection;

collection.push_back("London");collection.push_back("Madrid");collection.push_back("New York");collection.push_back("Tokyo");collection.push_back("Rome");

for (unsigned i = 0; i < collection.size(); i++){

cout << collection[i] << endl;}

vector<string> collection;

collection.push_back("London");collection.push_back("Madrid");collection.push_back("New York");collection.push_back("Tokyo");collection.push_back("Rome");

for (unsigned i = 0; i < collection.size(); i++){

cout << collection[i] << endl;}

• Dynamic array– automatically expands when entries are added

#include <vector>#include <vector>

Use the vector class when you need a dynamic array. The array will automatically resize as elements are added. The underlying implementation takes care of the resizing, but typically this will reserve additional space to allow the array to expand. If the additional space is exhausted, the implementation may relocate the array and double its size. To avoid resizing, a constructor is provided that allows the caller to specify the initial size of the array.

Note that the [ ] operator is overloaded as a convenience to allow the array to be used like a C array. Unfortunately, the vector class does not provide bounds checking, although it is a simple matter to derive a class from vector and provide bounds checking via an overloaded [ ] operator function.

Page 74: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 74

Copyright ©1994-2010 CRS Enterprises 74

Vector using Iterators

vector<string> collection;

collection.push_back("London");collection.push_back("Madrid");collection.push_back("New York");collection.push_back("Tokyo");collection.push_back("Rome");

vector<string>::iterator i;

for (i = collection.begin(); i != collection.end() ; ++i){

cout << *i << endl;}

vector<string> collection;

collection.push_back("London");collection.push_back("Madrid");collection.push_back("New York");collection.push_back("Tokyo");collection.push_back("Rome");

vector<string>::iterator i;

for (i = collection.begin(); i != collection.end() ; ++i){

cout << *i << endl;}

• Iterator is a nested class of vector– random access iterator– overloaded operators ++ -- * == !=

In order to perform algorithms with the vector class you will need to use iterators. The vector class will supply a random access iterator. A simple example of using such an iterator is shown above.

Page 75: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 75

Copyright ©1994-2010 CRS Enterprises 75

List using Iterators

list<string> collection;

collection.push_back("London");collection.push_back("Madrid");collection.push_back("New York");collection.push_back("Tokyo");collection.push_back("Rome");

list<string>::iterator i;

for (i = collection.begin(); i != collection.end() ; ++i){

cout << *i << endl;}

list<string> collection;

collection.push_back("London");collection.push_back("Madrid");collection.push_back("New York");collection.push_back("Tokyo");collection.push_back("Rome");

list<string>::iterator i;

for (i = collection.begin(); i != collection.end() ; ++i){

cout << *i << endl;}

• Simple to change vector to list– illustrates similarity of methods

#include <list>#include <list>

The vector and list classes are designed to have a similar set of methods. Obviously, the implementations of the two classes are quite different; the list class implements a linked list and the vector an array.

The similarity of methods make it easy to convert our previous example from a vector implementation to a list implementation.

Page 76: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 76

Copyright ©1994-2010 CRS Enterprises 76

Maps ...

std::map <key_type, data_type, [comparison_function ]> std::map <key_type, data_type, [comparison_function ]>

map<string, Point> mymap; pair<string, Point> mypair;mypair.first = "point-1";mypair.second = Point(3,4);mymap.insert(mypair);

map<string, Point> mymap; pair<string, Point> mypair;mypair.first = "point-1";mypair.second = Point(3,4);mymap.insert(mypair);

• inserting

• inserting

• inserting

mymap.insert(make_pair("point-2", Point(4,5)));mymap.insert(make_pair("point-2", Point(4,5)));

mymap["point-3"] = Point(5,6);mymap["point-3"] = Point(5,6);

The Map class provides an insert method to add or modify entries. The insert method is overloaded, but the one shown above uses a pair object to specify the inserted element.

The pair class is a simple structure:

template <typename T1, typename T2>

struct pair

{

T1 first;

T2 second;

}

As you can see, using a pair is a little cumbersome, so the [ ] operator function (which calls insert) is often used in practice. Alternatively, use the make_pair function to set up the key-value pair.

Page 77: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 77

Copyright ©1994-2010 CRS Enterprises 77

... Maps

mymap.erase("point-2"); mymap.erase("point-2");

• searching

• searching

• erasing

map<string, Point> mymap; map<string, Point>::iterator i;i = mymap.find("point-3");string key = i->first;Point value = i->second;

map<string, Point> mymap; map<string, Point>::iterator i;i = mymap.find("point-3");string key = i->first;Point value = i->second;

ptr = mymap["point-2"];ptr = mymap["point-2"];

To look up a key in a map you can use the find method. The find method returns an iterator that points to a pair object. Again the the [ ] operator function is a convenience to simplify accessing the map.

To remove a key from a map use the erase method.

Page 78: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 78

Copyright ©1994-2010 CRS Enterprises 78

... Maps• vendors decide on implementation

– hash, tree

• no two elements have the same key– unique keys

• inserting – does not invalidate existing iterators

• erasing– does not invalidate existing iterators– except for iterators pointing to erased element

• multimap– like map, but can have duplicate keys

Vendors decide on the implementation of the Map, but typically will use a hash or tree implementation.

Maps have unique keys: no two elements have the same key (unique keys). Alternatively, if you need elements with duplicate keys you can use a multimap.

Map has the important property that inserting a new element into a map does not invalidate iterators that point to existing elements. Erasing an element from a map also does not invalidate any iterators, except, of course, for iterators that actually point to the element that is being erased.

Page 79: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 79

Copyright ©1994-2010 CRS Enterprises 79

Algorithms - find_if

list<Employee> collection;list<Employee>::iterator i;i = find_if(collection.begin(),

collection.end(), LessThan21K);

if(i != collection.end())i->Print();

elsecout << "not found" << endl;

list<Employee> collection;list<Employee>::iterator i;i = find_if(collection.begin(),

collection.end(), LessThan21K);

if(i != collection.end())i->Print();

elsecout << "not found" << endl;

bool LessThan21K(const Employee& e){

if (e.GetSalary() < 21000)return true;

elsereturn false;

}

bool LessThan21K(const Employee& e){

if (e.GetSalary() < 21000)return true;

elsereturn false;

}

The find_if algorithm is typical of those provided by the STL. The algorithm takes three parameters; the first two parameters are iterators which define the start and end of the range to be searched. The third parameter is a function pointer (or functor) that points to a predicate function (a function that returns true or false) which acts a callback mechanism.

The implementation will repeatedly callback on the predicate function with elements of the collection until either the function returns true or the end of the collection is reached. The algorithm returns an iterator to the selected element in the former case and the end iterator in the latter case.

Page 80: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 80

Copyright ©1994-2010 CRS Enterprises 80

C++11: More STL Containers• array<T, N>

– stores fixed size sequences of objects (N elements of type T); elements are stored contiguously

– avoid using a vector for fixed size sequences

• forward_list<T> singly linked list– constant time insert and erase operations; automatic storage management;

no fast random access

Several new containers have been added to the STL with C++11. Several hashed containers have been added, but the above containers augment the simpler vector and list containers.

The array container is a replacement of vector when you wish to store fixed size sequences of objects; elements are guaranteed to be stored contiguously. Obviously you could still use a vector in these situations, but the array has better performance and a better memory footprint. In fact the array is as efficient in terms of storage size as an ordinary array declared with the language's bracket syntax ([]). This class merely adds a layer of member and global functions to it, so that arrays can be used as standard container.

Forward lists are implemented as singly-linked lists; this differs from the list class which is a double linked list. Forward_list objects are thus more efficient than list objects, but only support forward iterators.

Page 81: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 81

Copyright ©1994-2010 CRS Enterprises 81

Functors• Functors pervade the STL

– behaves like a function with state– overload operator()

int main(){

vector<Point> points;points.push_back(Point(3,4));points.push_back(Point(5,12));points.push_back(Point(8,15));points.push_back(Point(7,24));points.push_back(Point(9,40));

// use a functorFunctor f;for_each(points.begin(), points.end(), f);

}

int main(){

vector<Point> points;points.push_back(Point(3,4));points.push_back(Point(5,12));points.push_back(Point(8,15));points.push_back(Point(7,24));points.push_back(Point(9,40));

// use a functorFunctor f;for_each(points.begin(), points.end(), f);

}

struct Functor{

double distance = 0.0;void operator() (const Point& p){

distance += p.distance();}

};

struct Functor{

double distance = 0.0;void operator() (const Point& p){

distance += p.distance();}

};

The STL defines a large number of algorithms to be used in conjunction with the STL containers. These algorithms normally are defined in terms of iterators and functors. A functor is simply an object that can impersonate a function pointer by overloading the function call operator (the round brackets operator). A functor differs from a function pointer in that being an object it can also have arbitrary state attached to it. This additional state is what makes functors so flexible.

It should be pointed out that function pointers could be used in place of functors, but functors are usually preferred.

Page 82: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 82

Copyright ©1994-2010 CRS Enterprises 82

Boost Smart Pointers• shared_ptr and weak_ptr now part of C++11

scoped_ptrscoped_ptr <boost/scoped_ptr.hpp><boost/scoped_ptr.hpp> Simple sole ownership of single objects. Noncopyable.

Simple sole ownership of single objects. Noncopyable.

scoped_arrayscoped_array <boost/scoped_array.hpp><boost/scoped_array.hpp> Simple sole ownership of arrays. Noncopyable.

Simple sole ownership of arrays. Noncopyable.

shared_ptrshared_ptr <boost/shared_ptr.hpp><boost/shared_ptr.hpp> Object ownership shared among multiple pointers.

Object ownership shared among multiple pointers.

shared_arrayshared_array <boost/shared_array.hpp><boost/shared_array.hpp> Array ownership shared among multiple pointers

Array ownership shared among multiple pointers

weak_ptrweak_ptr <boost/weak_ptr.hpp><boost/weak_ptr.hpp> Non-owning observers of an object owned by shared_ptr.

Non-owning observers of an object owned by shared_ptr.

intrusive_ptrintrusive_ptr <boost/intrusive_ptr.hpp><boost/intrusive_ptr.hpp> Shared ownership of objects with an embedded reference count

Shared ownership of objects with an embedded reference count

The Boost smart pointer library provides six smart pointer class templates. These classes provide smart pointers for heap based objects and arrays. Some of the classes provide direct ownership of bodies, whilst others provide reference counting.

Page 83: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 83

Copyright ©1994-2010 CRS Enterprises 83

Scoped Pointer• simple smart pointer handle - body

– manages body by taking ownership– copying not allowed

• used for automatic cleanup of heap based objects– handle on stack uses RAII

• can't be used with STL containers– because of non copy restriction

• alternative to auto_ptr– but transfer of body ownership is not allowed

The scoped_ptr is a simple smart pointer handle - body implementation where the handle manages the body by taking sole ownership. Unlike reference counted pointers, scoped pointers cannot be copied and die when they go out of scope.

The principal use of the scoped_ptr is for automatic cleanup of heap based objects using the Resource Acquisition is Initialization (RAII) idiom. This works because the handle is stack based and only the body is placed on the heap.

The non copy restriction implies that a scoped_ptr cannot be used with STL containers; use shared_ptr if that is your intention.

The scoped_ptr is an alternative to the STL auto_ptr and behaves similarly to a const auto_ptr in that transfer of body ownership is not allowed.

Page 84: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 84

Copyright ©1994-2010 CRS Enterprises 84

Scoped Array• simple smart pointer handle - body

– similar to scoped_ptr, but for arrays

• alternative to using std::vector– vector is much more flexible– but if its efficiency you are after ...

• can't be used with STL containers– because of non copy restriction

The scoped_array is used in the same way as scoped_ptr for heap based arrays. The STL already has the vector class for dynamic arrays and this should be preferred in most situations. However, the scoped _array is a very simple handle - body implementation and is therefore more efficient for fix sized arrays. So use vector unless efficiency is your primary concern.

Like the scoped_ptr, a scoped_array can't be copied and hence can't be used with STL containers.

Page 85: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 85

Copyright ©1994-2010 CRS Enterprises 85

Shared Pointer• reference counted pointer

– body is guaranteed to be deleted when the last shar ed_ptr pointing to it is destroyed

• every shared_ptr is Copy Constructible and Assignab le– therefore can be used in standard library container s

• with comparison operators– shared_ptr works with the standard library's associ ative containers

• be careful of cyclic references– use weak_ptr to "break cycles"

The shared_ptr is a reference counted pointer whose body is guaranteed to be deleted when the last shared_ptr pointing to it is destroyed.

Shared pointers are copy constructible and assignable - conditions that must be met before a class can be used in the STL. Thus shared_ptr can be used with standard library containers.

Furthermore, shared_ptr has comparison operators which allows it to be used with the standard library's associative containers.

As with all reference counted artefacts, you must be careful of cyclic references. You can use weak_ptr to "break cycles".

Page 86: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 86

Copyright ©1994-2010 CRS Enterprises 86

Shared Array• reference counted pointer to an array

– body is guaranteed to be deleted when the last shar ed_array pointing to it is destroyed

• like shared_ptr, these pointers can be used with– standard library containers– standard library's associative containers

• use vector ...– unless efficiency is primary concern

The shared_array is used with arrays to provide a reference counted handle body combination. The pointer is provided as an efficient alternative to the vector class. It can be used with both standard library containers and associative containers.

Page 87: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 87

Copyright ©1994-2010 CRS Enterprises 87

Weak Pointer ...• stores a weak reference to an object that's already

managed by a shared_ptr• to access the object, a weak_ptr can be converted t o a

shared_ptr – using the shared_ptr constructor or the member func tion lock

• when the last shared_ptr to the object goes away th e object is deleted

– attempts to obtain a shared_ptr from the weak_ptr w ill fail– constructor throws an exception boost::bad_weak_ptr– weak_ptr::lock returns an empty shared_ptr

• can be used with standard library containers and associative containers.

• weak_ptr operations never throw exceptions

The weak_ptr stores a weak reference to an object that's already managed by a shared_ptr. Weak references are use to break reference counted cycles.

Weak pointers can't access their body directly. To access the body, a weak_ptr can be converted to a shared_ptr using the shared_ptr constructor or the member function lock.

When the last shared_ptr to the object goes away the object is deleted, attempts to obtain a shared_ptr from the weak_ptr will fail. In the case of the constructor a boost::bad_weak_ptr exception is thrown and in the case of lock() an empty shared_ptr is returned.

Weak pointers can be used with standard library containers and associative containers.

Weak pointers operations never throw exceptions.

Page 88: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 88

Copyright ©1994-2010 CRS Enterprises 88

... Weak Pointer• often dangerous in multithreaded programs

– other threads can delete body without the weak poin ter noticing– a dangling pointer

shared_ptr<int> p(new int(5));weak_ptr<int> q(p);

// some time later

if(shared_ptr<int> r = q.lock()){

// use *r}

shared_ptr<int> p(new int(5));weak_ptr<int> q(p);

// some time later

if(shared_ptr<int> r = q.lock()){

// use *r}

create a temporaryshared_ptr from q

r holds a reference body. Reference count can't go to zero until were finished

Be careful with weak_ptr in multi-threaded programs. You need to guard against other threads releasing their shared_ptrs and the body getting deleted. If that happens the weak_ptr will become a dangling pointer.

To avoid this situation, create a temporary shared pointer from the weak pointer before you use it, effectively incrementing the reference count on the body by one and preventing the body being deleted prematurely.

Page 89: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 89

Copyright ©1994-2010 CRS Enterprises 89

Intrusive Pointer ...• intrusive_ptr stores a pointer to a body with an

embedded reference count– every intrusive_ptr increments/decrements the refer ence count by

using calls to intrusive_ptr_add_ref/intrusive_ptr_ release– user is expected to provide suitable definitions of these two functions

• intended for frameworks that provide reference coun ted class

– usually you should prefer shared_ptr

An intrusive_ptr stores a pointer to a body with an embedded reference count. The intrusive_ptr increments the reference count by using calls to intrusive_ptr_add_ref and decrements the reference count by using calls to intrusive_ptr_release.

These smart pointers are provided for compatibility with frameworks that already provide reference counted classes. Usually you should prefer to use shared_ptr.

Page 90: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 90

Page 91: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 91

Copyright ©1994-2010 CRS Enterprises 91

Using the STL Efficiently

4

This chapter investigates the Standard Template Library (STL). The STL provides an extensive set of data structures or containers and a large number of algorithms that operate on these containers.

Page 92: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 92

Copyright ©1994-2010 CRS Enterprises 92

• unordered_map (hash) ...– has best performance

Speed of Algorithms

insertremoveat front

insertremoveat front

insertremoveat back

insertremoveat back

searchsearch

vectorvector O(n)O(n)

listlist O(1)O(1)

setset O(log(n))O(log(n))

mapmap O(log(n))O(log(n))

unordered_mapunordered_map O(1)O(1)

O(1)O(1)

O(1)O(1)

O(log(n))O(log(n))

O(log(n))O(log(n))

O(1)O(1)

O(1) for operator[ ]O(n) for iterator

O(1) for operator[ ]O(n) for iterator

O(n)O(n)

O(log(n))O(log(n))

O(log(n))O(log(n))

O(1)O(1)

When using the STL it is important to choose the appropriate containers for your application. Part of this choice is to appreciate the performance of the container for common operations such as inserting and sorting:

O(1) is linear time; the same time for each operation.

O(log(n)) means that operation time increases as the log of the size of the collection. However the increase is slight, for example a 1000 fold increase in the size of the container means the operation time only increases by a factor of 3.

O(n) means the operation time increases proportionally with the size of the collection. This could be a serious performance limitation if the operation is used repeatedly. Hence vectors should not be used for insert/remove operations on the front of the collection. Likewise list should be avoided for search operations. Note that the hashed containers provide he best performance metrics.

Page 93: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 93

Copyright ©1994-2010 CRS Enterprises 93

STL : Pass by Value• Pass by value semantics

– Vector classes need efficient– default CTOR, assignment operator

• Slicing– pass by value implies slicing

– problem with polymorphic types

The STL uses pass by value semantics throughout (if you need reference semantics you can always store pointers in your containers). Hence there a great deal of copying objects going on behind the scenes. This in turn means you should be careful in designing classes destined to be stored in containers.

In particular, you will improve performance if your default constructor, copy constructor and assignment operator are written to be as fast as possible. With the new C++11 standard it is also important to provide an efficient move constructor (but these tend to be very efficient in any case).

Bear in mind that pass by value implies objects are copied. If you are working with polymorphic objects this implies slicing (the derived parts are sliced off) with disastrous results. So do not use polymorphic objects directly when using the STL. If you must work with polymorphic collections, use some form of handle-body with a non-polymorphic collection of handles. You can then safely define the body as polymorphic.

pass by value implies slicing

problem with polymorphic types

Page 94: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 94

Copyright ©1994-2010 CRS Enterprises 94

Your Classes should have ...• Several STL containers automatically resize when fu ll

– resizing involves implicit and extensive use of cop y, assign, and destroy the container's elements

• Important for classes ...– to have an efficient

– default constructor – copy constructor– destructor– assignment operator

Several STL containers automatically resize when full and resizing involves implicit and extensive use of copy, assign, and destroy the container's elements.

So as discussed previously it is important for classes to be defined with an efficient default constructor, copy constructor, destructor and assignment operator.

Page 95: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 95

Copyright ©1994-2010 CRS Enterprises 95

Exception Safety• The C++ Standard Library guarantees:

– library will not leak resources or violate containe r invariants (prescribed states) if an exception occurs

– an operation has no effect if an exception is throw n

• Hence - commit or rollback or transaction safe actio n– any failure to construct an element in a containers (list, set multiset,

map, multimap) leaves the container as it was– removing a node cannot fail– single-element insertion in an associative containe r is transaction safe– all erase operations of both either one element or multiple elements

always succeed

When working with the STL, realise that the C++ Standard Library guarantees that the library will not leak resources or violate container invariants (prescribed states) if an exception occurs. This means that an operation has no effect on a collection if an exception is thrown.

Hence containers support transaction semantics.

Page 96: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 96

Copyright ©1994-2010 CRS Enterprises 96

Invalidated Iterators• Vector elements easily become invalidated:

• Inserting elements invalidates ...– all iterators, pointers, and references to elements after those inserted– but note reallocation below

• Deleting elements invalidates ...– all iterators, pointers, and references to elements after those deleted

• Destruction of the vector invalidates ...– all iterators, pointers, and references to elements .

• Reallocation invalidates ...– all iterators, pointers, and references to elements

Be careful when working with the STL not to use invalidated iterators. Several operations can invalidate iterators and their subsequent use is the source of many bugs.

In particular, inserting elements invalidates all iterators, pointers, and references to elements after those inserted. Deleting elements invalidates all iterators, pointers, and references to elements after those deleted. Destruction of the vector invalidates all iterators, pointers, and references to elements. Reallocation invalidates everything.

Page 97: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 97

Copyright ©1994-2010 CRS Enterprises 97

Containers don't clean up Pointers• Containers will clean up their contents

– if contents are objects– but not if they are pointers

– container might not have ownership of objects

vector<Point*> v;v.push_back(new Point(2,1));v.push_back(new Point(3,2));v.push_back(new Point(5,3));v.push_back(new Point(7,4));v.push_back(new Point(11,5));v.push_back(new Point(13,6));

// clean up memoryfor(int i = 0; i < v.size(); i++){

delete v[i];}

vector<Point*> v;v.push_back(new Point(2,1));v.push_back(new Point(3,2));v.push_back(new Point(5,3));v.push_back(new Point(7,4));v.push_back(new Point(11,5));v.push_back(new Point(13,6));

// clean up memoryfor(int i = 0; i < v.size(); i++){

delete v[i];}

A common source of error with the STL is to assume containers will clean up their contents when they go out of scope. While this is true for containers of objects, it is not true for containers of pointers. This is by design, since with pointers the container has no way of knowing if it has ownership of the target objects. You always have the option of using smart pointers to ensure correct cleanup of heap based objects. This also helps to ensure your code is exception safe.

However, if you are not using smart pointers, it is your responsibility to traverse the container calling delete on all your heap based objects.

Page 98: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 98

Copyright ©1994-2010 CRS Enterprises 98

Display Container on Standard Output• Use copy algorithm ...

– coupled with ostream_iterator

vector<int> v = {2,3,5,7,11,13,17,19};copy(v.begin(), v.end(), ostream_iterator <int>(cout, ","));

string s( "Supercalifragilisticexpialidocious");copy(s.begin(), s.end(), ostream_iterator <char>(cout, "-"));

vector<int> v = {2,3,5,7,11,13,17,19};copy(v.begin(), v.end(), ostream_iterator <int>(cout, ","));

string s( "Supercalifragilisticexpialidocious");copy(s.begin(), s.end(), ostream_iterator <char>(cout, "-"));

When debugging STL code it can be quite useful to output the contents of the container. The STL copy algorithm is ideal for this purpose. Copy takes three parameters: the first two define the range and the third is an iterator. By choosing an ostream_iterator you can output your objects in a typesafe manner. You can write an overloaded ostream_iterator for containers of user defined objects.

Page 99: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 99

Copyright ©1994-2010 CRS Enterprises 99

Copying C-Style Arrays• C Style arrays have iterators• use copy algorithm

– to copy array to vector

– to copy array to stdout

const float cost[4] = { 4.78, 6.97, 8.81, 9.02 };vector<float> v(4);copy(cost , cost+4 , v.begin());

const float cost[4] = { 4.78, 6.97, 8.81, 9.02 };vector<float> v(4);copy(cost , cost+4 , v.begin());

const float cost[4] = { 4.78, 6.97, 8.81, 9.02 };copy(cost , cost+4 , ostream_iterator<float>(cout, ","));

const float cost[4] = { 4.78, 6.97, 8.81, 9.02 };copy(cost , cost+4 , ostream_iterator<float>(cout, ","));

It is often overlooked that C pointers are a type of iterator and therefore can be used in STL algorithms. The example above shows how to copy parts of a C style array to an STL vector and to standard out.

Page 100: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 100

Copyright ©1994-2010 CRS Enterprises 100

vector<int> v = {2,3,5,7,11,13};

cout << v[5] << endl; cout << v.at(5) << endl;

try{

cout << v[55] << endl;cout << v.at(55) << endl;

}catch(out_of_range & e){

cout << e.what() << endl;}

vector<int> v = {2,3,5,7,11,13};

cout << v[5] << endl; cout << v.at(5) << endl;

try{

cout << v[55] << endl;cout << v.at(55) << endl;

}catch(out_of_range & e){

cout << e.what() << endl;}

Vector: Checked Access• operator[ ] does not perform range checking• at() does

– throws out_of_range

doesn't check for valid index

checks for valid index

Be aware that when working with vectors you have a choice of accessing objects either through the [ ] operator or using the at method. The at method is safest because it incorporates range checking and will throw if you are out of bounds. Range checking comes at a price, so operator[ ] is preferred if you don't need range checking and speed is paramount.

Page 101: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 101

Copyright ©1994-2010 CRS Enterprises 101

Use Reserve• Containers will continually reallocate as the conta iner

grows– use reserve to avoid unnecessary reallocations

– to avoid unnecessary copying and deleting

vector<Point> v;v.reserve (6);v.push_back(Point(2,1));v.push_back(Point(3,2));v.push_back(Point(5,3));v.push_back(Point(7,4));v.push_back(Point(11,5));v.push_back(Point(13,6));

vector<Point> v;v.reserve (6);v.push_back(Point(2,1));v.push_back(Point(3,2));v.push_back(Point(5,3));v.push_back(Point(7,4));v.push_back(Point(11,5));v.push_back(Point(13,6));

STL containers are designed to grow automatically. While this is a convenience for programming, realize that the container will continually reallocate as the container grows and this could result in very poor performance.

If you know roughly how big your collection is likely to be, it is a very good idea to use reserve to avoid unnecessary reallocations and hence avoid unnecessary copying and deleting of container objects. This can improve performance enormously.

Page 102: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 102

Copyright ©1994-2010 CRS Enterprises 102

Vectors: Swap trick• Use swap to remove excess capacity from a vector

vector<double> v(10000);cout << "capacity = " << v.capacity() << " size = " << v.size() << endl;

v.clear() ;cout << "CLEAR: ";cout << "capacity = " << v.capacity() << " size = " << v.size() << endl;

// swap v with temporary vector of same typevector<double>().swap(v) ;cout << "SWAP: ";cout << "capacity = " << v.capacity() << " size = " << v.size() << endl;

vector<double> v(10000);cout << "capacity = " << v.capacity() << " size = " << v.size() << endl;

v.clear() ;cout << "CLEAR: ";cout << "capacity = " << v.capacity() << " size = " << v.size() << endl;

// swap v with temporary vector of same typevector<double>().swap(v) ;cout << "SWAP: ";cout << "capacity = " << v.capacity() << " size = " << v.size() << endl;

capacity = 10000 size = 10000CLEAR: capacity = 10000 size = 0SWAP: capacity = 0 size = 0

capacity = 10000 size = 10000CLEAR: capacity = 10000 size = 0SWAP: capacity = 0 size = 0

Vectors grow in size as new items are added to the container, but do not shrink when items are deleted. This can lead to vectors with a lot of wasted space.

By creating a new, temporary vector and calling its swap method the original vector will be resized. Its capacity and size will be just big enough to hold its elements - there will be no wasted space.

If this sounds like a lot of copying and allocation - bear in mind that this is what vector does every time it has to reallocate past its current reserved limit anyway.

Note the line:

vector<double>().swap(v)

this creates a temporary anonymous vector which gets deleted immediately its swap method is completed. The swap is achieved by building the temporary from the original vector's contents, but not copying the unused items, followed by swapping pointers (essentially a move operation) such that temporary holds the original contents and the original vector gets the rebuilt contents.

Page 103: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 103

Copyright ©1994-2010 CRS Enterprises 103

Sorting Lists• STL sort algorithm can't be used with List

– requires random-access iterators

• List has a member function to do sorting– two versions

void sort ( );void sort ( ); template <class Compare> void sort (Compare compare);

template <class Compare> void sort (Compare compare);

sort elements using operator< sort elements using Compare functor

The STL has an algorithm to sort containers that support random access iterators. However you can't use this algorithm with list or forward_list containers because they don't support random access iterators.

Instead the list and forward_list containers have their own optimized sort algorithm and this should be use instead.

Page 104: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 104

Copyright ©1994-2010 CRS Enterprises 104

Sort without Copying• If copying is an expensive operation, consider usin g

(smart) pointers to objects

int main(){

vector<Point*> v;v.reserve(6);v.push_back(new Point(11,5));v.push_back(new Point(5,3));v.push_back(new Point(2,1));v.push_back(new Point(7,4));v.push_back(new Point(13,6));v.push_back(new Point(3,2));

sort(v.begin(), v.end(), less_than_iterator );}

int main(){

vector<Point*> v;v.reserve(6);v.push_back(new Point(11,5));v.push_back(new Point(5,3));v.push_back(new Point(2,1));v.push_back(new Point(7,4));v.push_back(new Point(13,6));v.push_back(new Point(3,2));

sort(v.begin(), v.end(), less_than_iterator );}

bool less_than_iterator (Point* lhs, Point* rhs){

return *lhs < *rhs;}

bool less_than_iterator (Point* lhs, Point* rhs){

return *lhs < *rhs;}

Sometimes it is too expensive to sort a container of objects, perhaps because the objects are too big to copy efficiently.

In such cases consider storing pointers in the container and provide a custom iterator (comparator) to allow sorting the pointers. The container will now sort the pointers, swapping pointers as necessary. But swapping pointers will always be an efficient operation.

Page 105: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 105

Copyright ©1994-2010 CRS Enterprises 105

Search in Maps and Multimaps• Use member function for searching for keys• Use find or find_if algorithms for more complex

searches– e.g. searching for values

map<string,Employee> mymap;

map<string,Employee>::iterator i = mymap.find( "0201-492-8744" );if(i != mymap.end())

cout << "Found: " << i->first << "," << i->second << endl;else

cout << "Not found" << endl;

map<string,Employee> mymap;

map<string,Employee>::iterator i = mymap.find( "0201-492-8744" );if(i != mymap.end())

cout << "Found: " << i->first << "," << i->second << endl;else

cout << "Not found" << endl;

Maps and multimaps store key-value pairs. A map or multimap gives you extremely fast searching of and access to elements by key, provided you use the containers’ find member function.

The find or find_if STL algorithms will work, but they’ll be much slower. Occasionally, however, you might need to search in a map or multimap for a value, not a key and in this case use the more generic STL algorithms.

Page 106: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 106

Copyright ©1994-2010 CRS Enterprises 106

Choose map::insert• Choose map::insert rather than map::operator[ ]

– when creating new entries in a map

• Operator[ ] performs the follow tasks:– 1) creates a new key– 2) creates new value using default CTOR– 3) overwrites the value with its new value

• Insert() avoids step 2

MAP theList;

// use insert for new entriestheList.insert (MAP::value_type("Mary", 18000));theList.insert (MAP::value_type("John", 20000));theList.insert (MAP::value_type("Susan", 36500));theList.insert (MAP::value_type("Rose", 17500));theList.insert (MAP::value_type("Steven", 26000));

MAP theList;

// use insert for new entriestheList.insert (MAP::value_type("Mary", 18000));theList.insert (MAP::value_type("John", 20000));theList.insert (MAP::value_type("Susan", 36500));theList.insert (MAP::value_type("Rose", 17500));theList.insert (MAP::value_type("Steven", 26000));

Maps are an efficient associative container. However you need to be aware that there are two ways of inserting new entries into a map:

map::insert

map::operator[ ]

You should choose map::insert rather than map::operator[ ] when creating new entries in a map for performance reasons. Operator[ ] performs the follow tasks:

1) creates a new key

2) creates new value using default CTOR

3) overwrites the value with its new value

but insert() avoids step 2 and hence is faster.

Page 107: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 107

Copyright ©1994-2010 CRS Enterprises 107

Choose map::operator[]• Choose map::operator[ ] rather than map::insert whe n

updating existing entries in a map

MAP theList;

// use insert for new entriestheList.insert(MAP::value_type("Mary", 18000));theList.insert(MAP::value_type("John", 20000));theList.insert(MAP::value_type("Susan", 36500));theList.insert(MAP::value_type("Rose", 17500));theList.insert(MAP::value_type("Steven", 26000));

// use operator[ ] to update entriestheList ["Mary"] = 18050;theList ["John"] = 20050;theList ["Susan"] = 36550;theList ["Rose"] = 17550;theList ["Steven"] = 26050;

MAP theList;

// use insert for new entriestheList.insert(MAP::value_type("Mary", 18000));theList.insert(MAP::value_type("John", 20000));theList.insert(MAP::value_type("Susan", 36500));theList.insert(MAP::value_type("Rose", 17500));theList.insert(MAP::value_type("Steven", 26000));

// use operator[ ] to update entriestheList ["Mary"] = 18050;theList ["John"] = 20050;theList ["Susan"] = 36550;theList ["Rose"] = 17550;theList ["Steven"] = 26050;

insert creates default constructed value_type entry and then overwrites it

operator[ ] does do the unnecessary step

Unfortunately, the reverse situation occurs when updating an existing entry in a map, This time operator[ ] is more efficient whereas insert creates an unnecessary temporary object.

Page 108: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 108

Copyright ©1994-2010 CRS Enterprises 108

Use hashed containers• No hashed containers in C++98

– standards committee ran out of time to approve them– performance issue

• Fixed in C++11– 4 standard containers

•unordered_map<Key, T> hash table–unique keys; supports forward iterators

•unordered_multimap<Key, T> hash table–can contain multiple copies of each key; supports forward iterators

•unordered_set<T> –unique elements and fast retrieval of values; supports forward iterators

•unordered_multiset<T> –can contain multiple copies of the same element and provides fast retrieval of the values; supports forward iterators

•unordered_map<Key, T> hash table–unique keys; supports forward iterators

•unordered_multimap<Key, T> hash table–can contain multiple copies of each key; supports forward iterators

•unordered_set<T> –unique elements and fast retrieval of values; supports forward iterators

•unordered_multiset<T> –can contain multiple copies of the same element and provides fast retrieval of the values; supports forward iterators

A key problem with the C++98 standard was the absence of hashed containers. This was done because of time pressures in releasing the standard, but has proved an unfortunate omission. Fortunately this has been fixed in C++11 and 4 standard hashed containers have been introduced.

The new hashed containers are faster than their tree container counterparts (map, multimap etc) and should be preferred. Performance of hashed containers is O(1) or constant, whereas the tree based containers have O(log(n)) performance.

Page 109: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 109

Copyright ©1994-2010 CRS Enterprises 109

Using istreambuf_iterators• Strings can be defined through a template

– taking input iterators as parameters

• istream_iterators ...– ignores whitespace

• istreambuf_iterators ...– reads every character including whitespace

template<class InputIterator> string (InputIterator begin, InputIterator end); template<class InputIterator> string (InputIterator begin, InputIterator end);

ifstream inputFile(fileName);string dataFromFile((istream_iterator<char >(inputFile)),

istream_iterator<char >());

ifstream inputFile(fileName);string dataFromFile((istream_iterator<char >(inputFile)),

istream_iterator<char >());

ifstream inputFile(fileName);string dataFromFile((istreambuf_iterator<char >(inputFile)),

istreambuf_iterator<char >());

ifstream inputFile(fileName);string dataFromFile((istreambuf_iterator<char >(inputFile)),

istreambuf_iterator<char >());

EOF iterator

most vexing parse

Many C++ programmers are unaware of the istreambuf_iterators and instead use istream_iterators for reading data from files. However you will soon find that istream_iterators called the standard operator>> functions which normally ignore whitespace. By using istreambuf_iterators you circumvent the whitespace problem.

Page 110: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 110

Copyright ©1994-2010 CRS Enterprises 110

Use accumulate for Mapping a Range• Accumulate applies a functor to a range

vector<Point> points;points.push_back({5,6});points.push_back({7,2});points.push_back({3,5});points.push_back({4,6});points.push_back({8,6});

Point average = accumulate(points.begin(), points.end(), Point(0, 0), PointAverage() );

cout << average.x << "," << average.y << endl;

vector<Point> points;points.push_back({5,6});points.push_back({7,2});points.push_back({3,5});points.push_back({4,6});points.push_back({8,6});

Point average = accumulate(points.begin(), points.end(), Point(0, 0), PointAverage() );

cout << average.x << "," << average.y << endl;

class PointAverage {const Point operator() (

const Point& runningAverage, const Point& next)

{count++;xTotal += next.x;yTotal += next.y;return Point(xTotal/count, yTotal/count);

}...};

class PointAverage {const Point operator() (

const Point& runningAverage, const Point& next)

{count++;xTotal += next.x;yTotal += next.y;return Point(xTotal/count, yTotal/count);

}...};

call functor for each element in range

Accumulate is a useful STL algorithm for performing calculations across a complete collection. The above example calculates the average coordinates for a point from a given collection.

The accumulate algorithm uses a functor to compute the average.

The algorithm takes two parameters to specify the range to be iterated, the third parameter specifies the starting value to be passed to the functor (not shown) and the fourth parameter is the call to the functor (note the brackets to call the functor) which performs the averaging.

Page 111: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 111

Copyright ©1994-2010 CRS Enterprises 111

stringstream• stringstream is an in memory file

– supports >> and << operators– can convert to string and cstring #include <sstream>

stringstream ss;

#include <sstream>stringstream ss;

stringstream ss;ss << 27 << string("abc") << "xyz";string s = ss.str() ;char cs[32];strcpy(cs, ss.str().c_str() ;

stringstream ss;ss << 27 << string("abc") << "xyz";string s = ss.str() ;char cs[32];strcpy(cs, ss.str().c_str() ;

For completeness we should mention the stringstream class. This represents an in memory file and supports >> and << extraction and insert operators. This is a very useful class and can convert objects to string and cstring and vice versa. As already mentioned, you might prefer to use a lexical cast.

Page 112: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 112

Copyright ©1994-2010 CRS Enterprises 112

Don't use auto_ptrs• Standard Library auto_ptr (deprecated in C++ 2011 )

– manages body by taking ownership– body belongs to only one auto_ptr– can be used for automatic cleanup of heap based obj ects

• Auto_ptrs don't have normal copy and assignment semantics

– can't be used with STL

auto_ptr<person> peter(new person("Peter"));auto_ptr<person> smithsmith = peter;

auto_ptr<person> peter(new person("Peter"));auto_ptr<person> smithsmith = peter;

As a final note in the chapter, avoid the use of auto_ptr. This class has caused much confusion and introduced obscure bugs into code because of its unusual semantics. Auto_ptrs are incompatible with the STL (a major problem) and are now deprecated in the new standard.

Page 113: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 113

Page 114: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 114

Copyright ©1994-2010 CRS Enterprises 114

Boost (Part 1)

5

This chapter investigates the Standard Template Library (STL). The STL provides an extensive set of data structures or containers and a large number of algorithms that operate on these containers.

Page 115: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 115

Copyright ©1994-2010 CRS Enterprises 115

What is Boost• Free peer-reviewed portable C++ source libraries

– license is very similar to the BSD license and the MIT license– written by professional C++ programmers– work well with the C++ Standard Library– in regular use by thousands of programmers

• Boost libraries are suitable for standardization– Many Boost libraries are part of the C++ 2011 Stand ard– many other useful libraries

• Template Based– most of the Boost libraries are distributed as temp lates– some compile to shared objects or DLLs

Boost provides free peer-reviewed portable C++ source libraries. The emphasis is on libraries which work well with the C++ Standard Library. The libraries are intended to be useful across a broad spectrum of applications and are in regular use by thousands of programmers.

A further goal is to establish "existing practice" and provide reference implementations so that Boost libraries are suitable for eventual standardization. Several Boost libraries will are included in the C++ 2011 Standard Library.

Although Boost was begun by members of the C++ Standards Committee Library Working Group, participation has expanded to include thousands of programmers from the C++ community at large.

Many of the Boost libraries are pure templates and therefore only require a compile step. However, a few of the libraries do need to be built into shared objects or DLLs.

Page 116: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 116

Copyright ©1994-2010 CRS Enterprises 116

Boost Web Site• Visit the Boost home page

– http://www.boost.org/

The Boost web site provides free peer-reviewed portable C++ source libraries. Downloads are available for all libraries, and for those requiring shared objects (or DLLs) a build facility is provided.

Complete documentation, FAQ and many tutorials are available on the site, plus links to mail groups and support.

Page 117: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 117

Copyright ©1994-2010 CRS Enterprises 117

Just Some of the Libraries ...• Any

– is a variant value type supporting copying of any v alue type and safe checked extraction of that value strictly against its type

• Assign – makes it easy to fill containers with lists of data by overloading operator,() and

operator()()

• Bind and Function– generalization of the callback mechanism supporting arbitrary function objects,

functions, function pointers, and member function p ointers

• Regex– regular expression engine integrates with STL string class

• Spirit– recursive-descent parser generator framework implem ented using template

meta-programming; enables a target grammar to be wr itten exclusively in C++

• uBLAS– templated C++ classes for dense, unit and sparse ve ctors, dense, identity,

triangular, banded, symmetric, hermitian and sparse matrices

The complete Boost library is too extensive to be covered in this chapter. Instead, we will investigate examples from the above libraries in subsequent pages.

Page 118: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 118

Copyright ©1994-2010 CRS Enterprises 118

Library Versions• Debug and Release versions available

– dynamic and static linking

• Naming Conventions– mt multi-threaded library– s statically linked– d no optimization or inlining, full debug symbols en abled

In order to choose the right binary for your build configuration you need to know how Boost binaries are named. Each library filename is composed of a common sequence of elements that describe how it was built. For example, libboost_regex-vc71-mt-d-1_34.lib can be broken down into the following elements:

lib

Prefix: except on Microsoft Windows, every Boost library name begins with this string. On Windows, only ordinary static libraries use the lib prefix; import libraries and DLLs do not.

boost_regex

Library name: all boost library filenames begin with boost_.

-vc71

Toolset tag: identifies the toolset and version used to build the binary.

-mt

Threading tag: indicates that the library was built with multithreading support enabled. Libraries built without multithreading support can be identified by the absence of -mt.

-d

ABI tag: encodes details that affect the library's interoperability with other compiled code.

Page 119: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 119

Copyright ©1994-2010 CRS Enterprises 119

Compiling• Project properties

– set the include paths

The settings dialog allows you to set various compiler options. In this instance we are specifying the location of the boost header files (same as the boost installation directory).

Page 120: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 120

Copyright ©1994-2010 CRS Enterprises 120

Compiling for C++ 2011• Project properties

– set miscellaneous options ( -std=c++0x )

If you want to use C++ 2011 features that have been implemented in GCC then add the following to the miscellaneous setting:

-std=c++0x

Page 121: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 121

Copyright ©1994-2010 CRS Enterprises 121

Linking• Project properties

– set library options (library and path)

For libraries, you must specify both the library to be used and the full path to the library. On windows platforms, use the MinGW C++ Linker settings to do this.

Page 122: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 122

Copyright ©1994-2010 CRS Enterprises 122

Any

int main(){// sample data

int i = 100;double d = 4.53;string myString("mystring");char* myCharArray = "charArray";

// build list of mixed typesLIST_OF_ANY myList;myList.push_back(i);myList.push_back(d);myList.push_back(myString);myList.push_back(myCharArray);

// iterate through list to determine typefor_each(myList.begin(),

myList.end(), DetermineType);

}

int main(){// sample data

int i = 100;double d = 4.53;string myString("mystring");char* myCharArray = "charArray";

// build list of mixed typesLIST_OF_ANY myList;myList.push_back(i);myList.push_back(d);myList.push_back(myString);myList.push_back(myCharArray);

// iterate through list to determine typefor_each(myList.begin(),

myList.end(), DetermineType);

}

#include <boost/any.hpp>using namespace std;

typedef std::list<boost::any> LIST_OF_ANY;using boost::any_cast;

#include <boost/any.hpp>using namespace std;

typedef std::list<boost::any> LIST_OF_ANY;using boost::any_cast;

void DetermineType(boost::any& operand){

try{

if(any_cast<int>(operand))cout << "int" << endl;

}catch(const boost::bad_any_cast &) {}

if(operand.type() == typeid(double))cout << "double" << endl;

if(operand.type() == typeid(string))cout << "string" << endl;

if(operand.type() == typeid(char*))cout << "char*" << endl;

}

void DetermineType(boost::any& operand){

try{

if(any_cast<int>(operand))cout << "int" << endl;

}catch(const boost::bad_any_cast &) {}

if(operand.type() == typeid(double))cout << "double" << endl;

if(operand.type() == typeid(string))cout << "string" << endl;

if(operand.type() == typeid(char*))cout << "char*" << endl;

}

The idea behind this library is to be able to compose lists of variant value types such that type information is retained. When retrieving an Any object from a container the type information can be inferred using a cast

if(any_cast<int>(operand))

where a boost::bad_any_cast exception is thrown if the cast fails.

Alternatively you can use the boost::Any::type() method

if(operand.type() == typeid(double))

Page 123: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 123

Copyright ©1994-2010 CRS Enterprises 123

Assign - Simple Example

#include <boost/assign/std/vector.hpp>#include <boost/assert.hpp>#include <iostream>using namespace std;using namespace boost::assign;

void Print(const int& i){

cout << i; cout.flush();}

int main(){

vector<int> values;// insert values at the end of the container

values += 1,2,3,4,5,6,7,8,9;

for_each(values.begin(), values.end(), Print);}

#include <boost/assign/std/vector.hpp>#include <boost/assert.hpp>#include <iostream>using namespace std;using namespace boost::assign;

void Print(const int& i){

cout << i; cout.flush();}

int main(){

vector<int> values;// insert values at the end of the container

values += 1,2,3,4,5,6,7,8,9;

for_each(values.begin(), values.end(), Print);}

• Overload +=– to make it easy to add to

the container

• Overload comma– to make it easy to form a

list

123456789123456789

This library makes it easy to form lists and add them to a container. It allows a Python like syntax by overloading the += and the comma operator.

Page 124: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 124

Copyright ©1994-2010 CRS Enterprises 124

Bind and Function ...• Bind library creates Function Objects

– generalization of the std::bind1st and std::bind2nd– supports arbitrary function objects, functions, fun ction pointers, and

member function pointers– able to bind any argument to a specific value

– or route input arguments into arbitrary positions– support placeholders _1,_2,_3, ... _9

• Function library contains templates that are function object wrappers

– similar to a generalized callback– often used with Bind

Function pointers and functors introduce complex syntax that has proved difficult for C++ newbie's. The bind library creates provides a simpler and consistent notation for such objects. In particular boost::bind treats free function and member functions in the same way (unlike in traditional C++).

Boost function objects are a generalization of the std::bind1st and std::bind2nd and supports arbitrary function objects, functions, function pointers, and member function pointers. These objects are able to bind any argument to a specific value or route input arguments into arbitrary positions. Function objects support placeholders _1,_2,_3, ... _9 to represent parameters.

The function library contains templates that are function object wrappers similar to a generalized callback. Internally the library uses C++ .* and ._> operators.

Page 125: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 125

Copyright ©1994-2010 CRS Enterprises 125

... Bind and Function

int main(){

// create binderboost::function<int(int)> binder;

// bind to a global functionbinder = &DoubleIt;

// invoke binderint result = binder(5);

// try it with objects and member functionsA a(100);binder = boost::bind(&A::Add,a,_1);result = binder(2);

}

int main(){

// create binderboost::function<int(int)> binder;

// bind to a global functionbinder = &DoubleIt;

// invoke binderint result = binder(5);

// try it with objects and member functionsA a(100);binder = boost::bind(&A::Add,a,_1);result = binder(2);

}

#include <vector>#include <iostream>#include <boost/bind.hpp>#include <boost/function.hpp>#include <boost/assign/std/vector.hpp>using namespace std;using namespace boost::assign;

class A{private:

int x;public:

A(int x) : x(x) {}int Add(int y) { return x + y; }

};

int DoubleIt(int a) { return 2 * a; }

#include <vector>#include <iostream>#include <boost/bind.hpp>#include <boost/function.hpp>#include <boost/assign/std/vector.hpp>using namespace std;using namespace boost::assign;

class A{private:

int x;public:

A(int x) : x(x) {}int Add(int y) { return x + y; }

};

int DoubleIt(int a) { return 2 * a; }

• Note template parameter– when creating binder

_1 is parameter 1

This is an extensive library that is a generalization of the C++ callback mechanism. The library supports arbitrary function objects, functions, function pointers, and member function pointers. Examples of binding to functions and member function pointers are given above.

The callback objects are called binders and are created using the boost::function template. Note that in the example shown, the template takes a single parameter that defines the signature of the function being bound

int DoubleIt(int)

int A::Add(int)

Page 126: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 126

Copyright ©1994-2010 CRS Enterprises 126

Lambda• Creates anonymous functions

typedef boost::function<int(int,int,int)> FP;

int main(){

FP fp = (_1 + _2) * _3;

// call the functionint result = fp(2, 4, 10);cout << result << endl;

}

typedef boost::function<int(int,int,int)> FP;

int main(){

FP fp = (_1 + _2) * _3;

// call the functionint result = fp(2, 4, 10);cout << result << endl;

}int lambda_function(int _1, int _2, int _3){

return (_1 + _2) * _3;}

int lambda_function(int _1, int _2, int _3){

return (_1 + _2) * _3;}

behaves as if you create a function

In this example, fp is defined to be a function pointer that binds to three parameters, _1, _2 and _3 and will compute the expression:

(_1 + _2) * _3

The function can be called at any time, by supplying its 3 input parameters.

Page 127: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 127

Copyright ©1994-2010 CRS Enterprises 127

Regex

#include <string>#include <iostream>#include <iterator>#include <boost/regex.hpp>#include <boost/algorithm/string/regex.hpp>using namespace std;using namespace boost;

int main(){

string str1("abc__(456)__123__(123)__cde");

// Replace all substrings matching (digit+) replace_all_regex_copy( str1, regex("\\(([0-9]+)\\) "), string("#$1#") )

// Erase all substrings matching (letter+)erase_all_regex_copy( str1, regex("[[:alpha:]]+") )

// in-place regex transformationreplace_all_regex( str1, regex("_(\\([^\\)]*\\))_") , string("-$1-") );

}

#include <string>#include <iostream>#include <iterator>#include <boost/regex.hpp>#include <boost/algorithm/string/regex.hpp>using namespace std;using namespace boost;

int main(){

string str1("abc__(456)__123__(123)__cde");

// Replace all substrings matching (digit+) replace_all_regex_copy( str1, regex("\\(([0-9]+)\\) "), string("#$1#") )

// Erase all substrings matching (letter+)erase_all_regex_copy( str1, regex("[[:alpha:]]+") )

// in-place regex transformationreplace_all_regex( str1, regex("_(\\([^\\)]*\\))_") , string("-$1-") );

}

abc__#456#__123__#123#__cde__(456)__123__(123)__abc_-(456)-_123_-(123)-_cde

abc__#456#__123__#123#__cde__(456)__123__(123)__abc_-(456)-_123_-(123)-_cde

Regular Expressions are a form of pattern-matching that are often used in text processing. Many users will be familiar with the Unix utilities grep, sed and awk, and the programming language Perl, each of which make extensive use of regular expressions. Traditionally C++ users have been limited to the POSIX C API's for manipulating regular expressions, but these API's do not represent the best way to use the library. That's why the Boost library is needed.

The class boost::basic::regex is the key class in this library; it represents a "machine readable" regular expression, and is very closely modelled on std::basic_string. The library mimics the way regular expression patterns are defined in Perl.

Page 128: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 128

Copyright ©1994-2010 CRS Enterprises 128

Tuples• Tuple (or n-tuple) is a fixed size collection of elements

int main( ){

// creationtuple<int, double, string, Point> myTuple(1, 3.14, st ring("Hello"), Point(3,4));

// printingcout << myTuple << endl;

// make_tupledoit(2, 1.72, "Goodbye", Point(10,50));

// extractionint i = myTuple.get<0>(); cout << i << endl;double d = myTuple.get<1>(); cout << d << endl;string s = myTuple.get<2>(); cout << s << endl;Point p = myTuple.get<3>(); cout << p << endl;

}

int main( ){

// creationtuple<int, double, string, Point> myTuple(1, 3.14, string("Hello"), Point(3,4));

// printingcout << myTuple << endl;

// make_tupledoit(2, 1.72, "Goodbye", Point(10,50));

// extractionint i = myTuple.get<0>(); cout << i << endl;double d = myTuple.get<1>(); cout << d << endl;string s = myTuple.get<2>(); cout << s << endl;Point p = myTuple.get<3>(); cout << p << endl;

}

Tuples extend the C++98 Pair class to allow an arbitrary number of fields. This has been made possible by the introduction of variadic templates. Tuples have existed in other languages (e.g. Python) for many years.

Page 129: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 129

Copyright ©1994-2010 CRS Enterprises 129

Boost Smart Pointers

scoped_ptrscoped_ptr <boost/scoped_ptr.hpp><boost/scoped_ptr.hpp> Simple sole ownership of single objects. Noncopyable.

Simple sole ownership of single objects. Noncopyable.

scoped_arrayscoped_array <boost/scoped_array.hpp><boost/scoped_array.hpp> Simple sole ownership of arrays. Noncopyable.

Simple sole ownership of arrays. Noncopyable.

shared_ptrshared_ptr <boost/shared_ptr.hpp><boost/shared_ptr.hpp> Object ownership shared among multiple pointers.

Object ownership shared among multiple pointers.

shared_arrayshared_array <boost/shared_array.hpp><boost/shared_array.hpp> Array ownership shared among multiple pointers

Array ownership shared among multiple pointers

weak_ptrweak_ptr <boost/weak_ptr.hpp><boost/weak_ptr.hpp> Non-owning observers of an object owned by shared_ptr.

Non-owning observers of an object owned by shared_ptr.

intrusive_ptrintrusive_ptr <boost/intrusive_ptr.hpp><boost/intrusive_ptr.hpp> Shared ownership of objects with an embedded reference count

Shared ownership of objects with an embedded reference count

The Boost smart pointer library provides six smart pointer class templates. These classes provide smart pointers for heap based objects and arrays. Some of the classes provide direct ownership of bodies, whilst others provide reference counting.

Page 130: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 130

Copyright ©1994-2010 CRS Enterprises 130

Popular Libraries at Ericsson ...

Boost FileSystem

Boost Conversion

Boost DateTime

Page 131: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 131

Copyright ©1994-2010 CRS Enterprises 131

FileSystem• Filesystem permits us to write portable code

– to access files and directories from a C++ program

– without using the operating system specific system/library calls

• <boost/filesystem.hpp> – basic_path is a portable mechanism for representing paths in C++ programs

– typedefs path and wpath– operational functions provide useful query and maintenance operations on

files and directories– basic_directory_iterator

– typedefs directory_iterator and wdirectory_iterator provide iteration over the contents of directories

• <boost/filesystem /fstream.hpp>– provides the same components as fstream, except that files are identified

by basic_path objects rather that char *'s.

Filesystem permits us to write portable code to access files and directories from a C++ program without using the operating system specific system/library calls.

The <boost/filesystem.hpp> defines a basic_path class as a portable mechanism for representing paths in C++ programs. Typedefs path and wpath are provided for 8 and 16 bit names.

There are a large number of operational functions provided to perform useful query and maintenance operations on files and directories. Many of these functions utilise a basic_directory_iterator for iteration over the contents of directories.

Finally <boost/filesystem/fstream.hpp> provides the same components as fstream, except that files are identified by basic_path objects rather that char *'s.

Page 132: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 132

Copyright ©1994-2010 CRS Enterprises 132

Header Files• path.hpp

– key header file, defines path objects

– also provides functions for error checking

• operations.hpp– operations on files and directories.

• fstream.hpp– The C++ Standard Library's <fstream> header uses const char* to pass

arguments representing file names, with that usage occurring seven times.

– the header provides equivalent components to the C++ Standard Library's <fstream> with const char* arguments replaced by const path&

• exception.hpp– provides filesystem_error, publicly derived from std::runtime_error

• convenience.hpp– convenience functions that combine lower-level functions

The key header files for the library are shown above.

Page 133: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 133

Copyright ©1994-2010 CRS Enterprises 133

Paths• Portable mechanism for representing paths

– concerned with the lexical and syntactic aspects of a path

• The path does not have to exist – may contain names which are not even valid for the current operating system

namespace boost {

namespace filesystem {

class path{

... }

}}

namespace boost {

namespace filesystem {

class path{

... }

}}

< boost/filesystem/path.hpp>< boost/filesystem/path.hpp>

The class path provides a portable mechanism for representing paths and is concerned with the lexical and syntactic aspects of a path. Note that the path does not have to exist and may contain names which are not even valid for the current operating system. Functions are provided to check the validity of path names.

Page 134: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 134

Copyright ©1994-2010 CRS Enterprises 134

Paths• Specify using string or char*

– stored as an internal structure– may not exist

• name_check functions return True or False– portable_posix_name

– windows_name– portable_directory_name

– portable_file_name– no_check

namespace bfp = boost::filesystem::path;path();path(const char* pathname);path(const std::string& pathname);path(const char* pathname, bfp::name_check checker );path(const std::string& pathname, bfp::name_check checker );

namespace bfp = boost::filesystem::path;path();path(const char* pathname);path(const std::string& pathname);path(const char* pathname, bfp::name_check checker );path(const std::string& pathname, bfp::name_check checker );

Paths can by specified using string or char* (and their unicode equivalents). Paths are stored as an internal structure which can be query with name_check functions which return True or False:

portable_posix_name

windows_name

portable_directory_name

portable_file_name

no_check

Page 135: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 135

Copyright ©1994-2010 CRS Enterprises 135

Directory Iterator• directory_iterator is an input iterator which accesses the

contents of a directory

namespace boost {

namespace filesystem {

class directory_iterator{

...}

}}

namespace boost {

namespace filesystem {

class directory_iterator{

...}

}}

<boost/filesystem/operations.hpp><boost/filesystem/operations.hpp>

To traverse a directory, use a directory_iterator. directory_iterator steps though the contents of a given directory.

Page 136: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 136

Copyright ©1994-2010 CRS Enterprises 136

Filesystem Operations• lots of operations to apply on files

Operations functionsexistssymbolic_link_existsis_directoryis_emptylast_write_timecreate_directoryremoveremove_allrenamecopy_fileinitial_pathcompletesystem_complete

Operations functionsexistssymbolic_link_existsis_directoryis_emptylast_write_timecreate_directoryremoveremove_allrenamecopy_fileinitial_pathcompletesystem_complete

A huge number of functions can be used to examine paths, some of which are shown above.

Page 137: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 137

Copyright ©1994-2010 CRS Enterprises 137

C++ without Filesystem• Resort to O/S API

– e.g Windows and Linux

#include <windows.h>#include <stdio.h>

int main(){

DWORD status = GetFileAttributes (L"C:\\temp\\mydir");printf("Path is a directory : %d\n", status == FILE_ATTRIBUTE_DIRECTORY);return 0;

}

#include <windows.h>#include <stdio.h>

int main(){

DWORD status = GetFileAttributes (L"C:\\temp\\mydir");printf("Path is a directory : %d\n", status == FILE_ATTRIBUTE_DIRECTORY);return 0;

}

#include <sys/stat.h>#include <stdio.h>int main(){

struct stat s1;int status = stat("/tmp/mydir", &s1);printf("Path is a directory : %d\n", S_ISDIR(s1.st_mode));return 0;

}

#include <sys/stat.h>#include <stdio.h>int main(){

struct stat s1;int status = stat("/tmp/mydir", &s1);printf("Path is a directory : %d\n", S_ISDIR(s1.st_mode));return 0;

}

WindowsWindows

LinuxLinux

The Filesystem library is designed to avoid having to write operating system specific code like that shown above. These examples check if a file is of type directory, in Linux and in Windows. Note how different these code fragments are.

Page 138: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 138

Copyright ©1994-2010 CRS Enterprises 138

C++ with Filesystem• Filenames can be specified independent of O/S

– or use O/S format– can use / even in Windows

#include <iostream>#include <boost/filesystem.hpp>namespace fs = boost::filesystem;using namespace std;

int main(){

boost::filesystem::path path("/Temp/mydir");bool result = boost::filesystem::is_directory(path);cout << "Path is a directory : " << result << endl;return 0;

}

#include <iostream>#include <boost/filesystem.hpp>namespace fs = boost::filesystem;using namespace std;

int main(){

boost::filesystem::path path("/Temp/mydir");bool result = boost::filesystem::is_directory(path);cout << "Path is a directory : " << result << endl;return 0;

}

maps to C:\Temp\mydir

Here is the same example written in Filesystem. This code can be used on Windows or Linux (and other O/S). Note the filename "/Temp/mydir" maps to the current drive (probably C:) in Windows and that directory separators are specified Unix style.

Page 139: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 139

Copyright ©1994-2010 CRS Enterprises 139

Searching for Files• Use directory_iterator for searching

bool find_file ( const fs::path & dir_path,const std::string & file_name, fs::path & pfound) {

if (!exists (dir_path) || !is_directory (dir_path)) return false;fs::directory_iterator iter(dir_path), end_iter;

while(iter != end_iter) {if (is_directory (*iter)) {

if (find_file (*iter, file_name, pfound)) return true;} else if (iter->path().filename() == file_name) {

pfound = *iter;return true;

}++iter;

}return false;

}

bool find_file ( const fs::path & dir_path,const std::string & file_name, fs::path & pfound) {

if (!exists (dir_path) || !is_directory (dir_path)) return false;fs::directory_iterator iter(dir_path), end_iter;

while(iter != end_iter) {if (is_directory (*iter)) {

if (find_file (*iter, file_name, pfound)) return true;} else if (iter->path().filename() == file_name) {

pfound = *iter;return true;

}++iter;

}return false;

}

Here is a further example showing how to search for a file in a directory tree, Note that the routine makes use of recursion.

Page 140: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 140

Copyright ©1994-2010 CRS Enterprises 140

... Popular Libraries at Ericsson

Boost FileSystem

Boost Conversion

Boost DateTime

Page 141: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 141

Copyright ©1994-2010 CRS Enterprises 141

Conversion• Many ways to cast in C++

– vary with their ease of use, extensibility, and saf ety– atoi

– conversion in one direction only– only int, long, and double supported

– sprintf– inverse of atoi

– stringstream– great deal of control over the formatting and conve rsion – complicated

• Lexical Cast– convenient and consistent form for conversions– to and from arbitrary types when they are represent ed as text

– where the conversions are numeric to numeric, boost::numeric_cast may be faster

There are many ways to cast in C++, from the brackets cast though to static_cast, dynamic_cast etc. There are also library functions such as atoi and sprintf and the typesafe library class stringstream. All vary with their ease of use, extensibility, and safety.

The lexical cast is designed as a convenient and consistent form for conversions to and from arbitrary types when they are represented as text.

In cases where the conversions are numeric to numeric, boost::numeric_cast may be faster.

Page 142: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 142

Copyright ©1994-2010 CRS Enterprises 142

Conversion• Using cast like syntax

int main(){

string s1 = boost::lexical_cast<string> (2);string s2 = boost::lexical_cast<string> (8);cout << s1 + s2 << endl;

try{

double x1 = boost::lexical_cast<double> ("2.54");double x2 = boost::lexical_cast<double> ("2???54");

}catch(boost::bad_lexical_cast& e){

cout << "Exception caught - " << e.what() << endl;}

}

int main(){

string s1 = boost::lexical_cast<string> (2);string s2 = boost::lexical_cast<string> (8);cout << s1 + s2 << endl;

try{

double x1 = boost::lexical_cast<double> ("2.54");double x2 = boost::lexical_cast<double> ("2???54");

}catch(boost::bad_lexical_cast& e){

cout << "Exception caught - " << e.what() << endl;}

}

Here are some examples of using lexical_casts for converting integers to strings and strings to doubles. Note that a bad_lexical_cast is thrown if the cast fails.

Page 143: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 143

Copyright ©1994-2010 CRS Enterprises 143

• Lexical Cast much faster than other forms– e.g. performance figures from clang Linux 2.8

Conversion: Performance

lexical_castlexical_cast stringstreamstringstream printf/scanfprintf/scanf

string -> charstring -> char <1<1

string -> intstring -> int 44

string -> doublestring -> double 1818

int -> stringint -> string 1313

double -> stringdouble -> string 106106

1414

1919

9393

2323

122122

1212

1515

5858

1515

7676

Lexical casts not only use a more natural syntax than its predecessors, but generally speaking are more efficient. This is not always true, but the more common casts are very efficient.

Page 144: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 144

Copyright ©1994-2010 CRS Enterprises 144

C++98 Cast Operators• static_cast

– checks validity of cast at compile time

• dynamic_cast– checks validity of cast at run time

• const_cast– overrides const correctness during cast

• reinterpret_cast– casting between unrelated types

C++ has four new cast operators. These cast operators are designed to split the all embracing conventional cast into manageable categories. Conventional casts are often hard to spot and sometimes generate incorrect code. The new cast operators are intentionally verbose to highlight the cast and lend the full weight of the compiler to resolving problems.

Page 145: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 145

Copyright ©1994-2010 CRS Enterprises 145

static_cast1. Polymorphic Casts

compile time check if conversion is legal

2. Non-polymorphic Castscompile time check of casts between built-in types (int, double, etc)compile time check of casts between non pointer typ es

cast operators must be defined for classes concerne d

A a = static_cast<A>(b)A a = static_cast<A>(b)

static_cast can perform conversions between pointers to related classes, not only from the derived class to its base, but also from a base class to its derived. This ensures that at least the classes are compatible if the proper object is converted, but no safety check is performed during runtime to check if the object being converted is in fact a full object of the destination type. Therefore, it is up to the programmer to ensure that the conversion is safe. On the other side, the overhead of the type-safety checks of dynamic_cast is avoided.

Page 146: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 146

Copyright ©1994-2010 CRS Enterprises 146

reinterpret_castAllows any integral type to be converted into point er type

and vice versa

Always between Non Polymorphic Typesintent is to highlight cast between two apparently unrelated classes

may indicate a kludge or temporary fix

struct io_port{

unsigned char status;unsigned char data;

};

volatile io_port *iop = reinterpret_cast<io_port*>(0 xF878);

struct io_port{

unsigned char status;unsigned char data;

};

volatile io_port *iop = reinterpret_cast<io_port*>(0xF878);

pointer type integral type

The reinterpret_cast operator also allows any integral type to be converted into any pointer type and vice versa. Misuse of the reinterpret_cast operator can easily be unsafe. Unless the desired conversion is inherently low-level, you should use one of the other cast operators.

The reinterpret_cast operator can be used for conversions such as char* to int*, which is inherently unsafe.

The result of a reinterpret_cast cannot safely be used for anything other than being cast back to its original type. Other uses are, at best, nonportable.

The reinterpret_cast operator converts a null pointer value to the null pointer value of the destination type.

Page 147: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 147

Copyright ©1994-2010 CRS Enterprises 147

dynamic_cast ...

#include <vector>#include <string>#include <iostream>using namespace std;

struct Base { virtual void f() {} };

struct LX : public Base { virtual void lf() {} };struct LY : public LX { virtual void lf() {} };struct LZ : public LY { virtual void lf() {} };

struct RX : public Base { virtual void rf() {} };struct RY : public RX { virtual void rf() {} };struct RZ : public RY { virtual void rf() {} };

#include <vector>#include <string>#include <iostream>using namespace std;

struct Base { virtual void f() {} };

struct LX : public Base { virtual void lf() {} };struct LY : public LX { virtual void lf() {} };struct LZ : public LY { virtual void lf() {} };

struct RX : public Base { virtual void rf() {} };struct RY : public RX { virtual void rf() {} };struct RZ : public RY { virtual void rf() {} };

BaseBase

• cast performed at runtime

– null pointer returned on failure (pointers)

– or exception thrown (references)

LXLX RXRX

LYLY RYRY

LZLZ RZRZ

Consider the above inheritance hierarchy. If we create objects in this hierarchy. some casting operations will make sense while others will not. For example, can we cast to an LX class? Obviously only objects in classes derived from LX (i.e. LX, LY and LZ) satisfy this condition.

But how can we check for valid casts to LX at runtime? That's where the dynamic cast comes into its own. The dynamic cast will succeed for valid casts, but will return a null pointer if the cast is invalid.

Page 148: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 148

Copyright ©1994-2010 CRS Enterprises 148

... dynamic_cast

int main(){

vector<Base*> theList;

theList.push_back(new Base);theList.push_back(new LX);theList.push_back(new LY);theList.push_back(new LZ);theList.push_back(new RX);theList.push_back(new RY);theList.push_back(new RZ);

unsigned listSize = theList.size();for(unsigned i = 0; i < listSize; i++){

LX* p = dynamic_cast<LX*>(theList[i]);if(p) p->lf();

}}

int main(){

vector<Base*> theList;

theList.push_back(new Base);theList.push_back(new LX);theList.push_back(new LY);theList.push_back(new LZ);theList.push_back(new RX);theList.push_back(new RY);theList.push_back(new RZ);

unsigned listSize = theList.size();for(unsigned i = 0; i < listSize; i++){

LX* p = dynamic_cast<LX*>(theList[i]);if(p) p->lf();

}}

BaseBase

• LX, LY, LZ– IS A LX*– cast succeeds

• Base, RX, RY, RZ– null pointer returned

LXLX RXRX

LYLY RYRY

LZLZ RZRZ

Suppose we create a polymorphic collection of Base objects. According to the class hierarchy diagram, the objects in the collection can belong to any of the 7 classes (Base, LX, LY, LZ, RX, RY and RZ). As we iterate through the collection, we can use the dynamic cast to pick out objects that satisfy

object IS LX*

When this program is executed, the dynamic cast succeeds for the LX, LY and LZ objects, but a null pointer is returned for Base, RX, RY and RZ objects.

Dynamic casts can be applied to pointers and references

dynamic_cast<LX*>(ptr);

dynamic_cast<LX&>(ref);

Page 149: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 149

Copyright ©1994-2010 CRS Enterprises 149

const_castRemoves the const attribute of an object

can also be applied to volatile

void print(char * str){

cout << str << endl;}

int main (){

const char *c = "sample text";print(const_cast<char *> (c));

}

void print(char * str){

cout << str << endl;}

int main (){

const char *c = "sample text";print( const_cast<char *> (c) );

}

This type of casting removes the const (or volatile) attribute of an object.

This cast is normally only used with a function that has been written incorrectly such that it requires a non constant argument, but should require a const argument.

Page 150: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 150

Copyright ©1994-2010 CRS Enterprises 150

boost::polymorphic_cast• Equivalent to dynamic_cast• dynamic_cast is confusing

– returns 0 for pointers– throws for references

• polymorphic_cast– throws for both

A a;try{

B* pb = boost::polymorphic_cast <B*> (&a);pb->f();

}catch(const bad_cast& e){

cout << e.what() << endl;}

A a;try{

B* pb = boost::polymorphic_cast <B*> (&a);pb->f();

}catch(const bad_cast& e){

cout << e.what() << endl;}

One problem with the dynamic_cast is that it returns 0 for pointers when the cast fails, but throws an exception for reference casts that fail. This can be confusing.

The boost polymorphic_cast consistently throws exceptions in both cases and probably should be preferred.

Page 151: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 151

Copyright ©1994-2010 CRS Enterprises 151

... Popular Libraries at Ericsson

Boost FileSystem

Boost Conversion

Boost DateTime

Page 152: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 152

Copyright ©1994-2010 CRS Enterprises 152

Date Time - Domain Concepts• The library supports 3 basic temporal types:

• Time Point– location in the time continuum

• Time Duration– length of time unattached to any point on the time continuum

• Time Interval– duration of time attached to a specific point in th e time continuum– also known as a time period

The DateTime library supports 3 basic temporal types.

Time Point defines a location in the time continuum (a real time).

Time Duration defines a period of time, for example 2 weeks. This duration is not specified as a duration between two Time Points, but rather it is unattached to any point on the time continuum.

Time Interval, unlike Time Duration, is attached to a specific point in the time continuum. For example 2 weeks starting from 1 July 1975.

Page 153: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 153

Copyright ©1994-2010 CRS Enterprises 153

Gregorian Calendar• Julian Colander assumes

– 1 year = 365.25 days– should be 365.24218967 days

• Gregorian Calendar ...– first introduced in 1582 (but not everywhere)– more accurate than Julian Calendar– assumes 1 year = 365.2425 days

• Implementation extends dates back prior to 1582– current implementation supports dates in the range

– 1400-Jan-01 to 9999-Dec-31

• Types for the Gregorian system are found in – namespace boost::gregorian

– boost/date_time/gregorian/gregorian_types.hpp

The library is mainly concerned with specifying dates and times in terms of the Gregorian colander which has been in use in the west from 1582. The Gregorian calendar was commissioned by Pope Gregory XIII in a decree signed on 24 February 1582. However, because of political machinations, the colander was not accepted in some non Catholic countries until much later. Greece and Russia didn't adopt the Gregorian colander until the early part of the 20th century.

The Gregorian calendar has special rules for leap years on centuries. This means it is more accurate than Julian Calendar (which assumes 1 year is 365.2425 days). The new calendar represents a year of 365.2425 days when the actual figure should be 365.24218967 days. The difference won't manifest itself for a few tens of thousands of years - so no need to worry. Boost will no doubt be updated before then!

The DateTime implementation of the calendar extends dates back prior to 1582 and currently supports dates in the range from 1400-Jan-01 to 9999-Dec-31.

Types for the Gregorian system are found in the namespace boost::gregorian which is defined in the header file: boost/date_time/gregorian/gregorian_types.hpp.

Page 154: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 154

Copyright ©1994-2010 CRS Enterprises 154

Gregorian Dates• boost::gregorian::date

– is the primary temporal type for users

• Internally boost::gregorian::date is stored as a 32 bit integer type

– specifically designed to NOT contain virtual functi ons– allows for efficient calculation and memory usage w ith large

collections of dates.

boost::gregorian::date d(2010, 1, 30);cout << d.year() << endl;cout << d.month() << endl;cout << d.day() << endl;cout << d.day_of_week() << endl;cout << d.end_of_month() << endl;

boost::gregorian::date d(2010, 1, 30);cout << d.year() << endl;cout << d.month() << endl;cout << d.day() << endl;cout << d.day_of_week() << endl;cout << d.end_of_month() << endl;

boost::gregorian::date is the primary temporal type for users. It is easy to decompose these dates into constituent parts as shown above. Dates can be adjusted for the current locale including daylight savings.

Internally boost::gregorian::date is stored as a 32 bit integer type (as in the standard C library). The date type is specifically designed to NOT contain virtual functions so that large collections of dates will be stored efficiently.

Page 155: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 155

Copyright ©1994-2010 CRS Enterprises 155

Time Durations• boost::gregorian::date_duration

– is a simple day count used for arithmetic with greg orian::date– duration can be either positive or negative– typedef'd as days in the boost::gregorian namespace

boost::gregorian::date d1(1900, 1, 1);boost::gregorian::date d2(2000, 1, 1);boost::gregorian::date_duration dd = d2 - d1;cout << dd.days() << endl;

boost::gregorian::date d1(1900, 1, 1);boost::gregorian::date d2(2000, 1, 1);boost::gregorian::date_duration dd = d2 - d1;cout << dd.days() << endl;

boost::gregorian::date_duration is a simple day count used for arithmetic with gregorian::date. Duration can be either positive or negative and is typedef'd as days in the boost::gregorian namespace. Obviously, durations take into account the peculiarities of the Gregorian calendar's leap years.

Page 156: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 156

Copyright ©1994-2010 CRS Enterprises 156

Time Intervals• boost::gregorian::date_period

– provides direct representation for ranges between t wo dates– zero length periods are considered invalid– infinite length periods represent concepts such as 'until further notice'

boost::gregorian::date start(1952, 6, 2);boost::gregorian::date today = boost::gregorian::day_clock::local_day();boost::gregorian::date_period reign(start, today);boost::gregorian::date_duration dd = reign.length();cout << "The Queens reign has been for: ";cout << dd.days() << " days" << endl;

boost::gregorian::date start(1952, 6, 2);boost::gregorian::date today = boost::gregorian::day_clock::local_day();boost::gregorian::date_period reign(start, today);boost::gregorian::date_duration dd = reign.length();cout << "The Queens reign has been for: ";cout << dd.days() << " days" << endl;

boost::gregorian::date_period provides a direct representation for ranges between two dates. The date period can easily be converted to a duration, but other methods will allow you determine the first and last days of the period or more interesting properties such as the third Sunday in the range. Such queries illustrate the difference between a time interval and a time duration (where the third Sunday is meaningless).

Page 157: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 157

Copyright ©1994-2010 CRS Enterprises 157

Date Iterators• Used to generate range of dates

date startOfMonth = date(year, month, 1);int last_day = gregorian_calendar::end_of_month_day(year, month);date endOfMonth(year, month, last_day);

for (day_iterator i = startOfMonth; i <= endOfMonth; ++i){

cout << *i << " [" << i->day_of_week() << "]" << endl;}

date startOfMonth = date(year, month, 1);int last_day = gregorian_calendar::end_of_month_day(year, month);date endOfMonth(year, month, last_day);

for (day_iterator i = startOfMonth; i <= endOfMonth; ++i){

cout << *i << " [" << i->day_of_week() << "]" << endl;}

2012-Jun-01 [Fri]2012-Jun-02 [Sat]2012-Jun-03 [Sun]...2012-Jun-28 [Thu]2012-Jun-29 [Fri]2012-Jun-30 [Sat]

2012-Jun-01 [Fri]2012-Jun-02 [Sat]2012-Jun-03 [Sun]...2012-Jun-28 [Thu]2012-Jun-29 [Fri]2012-Jun-30 [Sat]

Date iterates (as the name suggests), generate collections of dates. For example, the iterator above generates all the dates in June 2012.

Page 158: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 158

Copyright ©1994-2010 CRS Enterprises 158

Posix Time System• ptime

– time system with nano-second/micro-second resolutio n– nano-second resolution uses 96 bits– micro-second resolution uses 64 bits

date d(2002, Feb, 1);ptime t1(d, hours(5) + minutes(4) + seconds(2) + millisec(1));

date d(2002, Feb, 1);ptime t1(d, hours(5) + minutes(4) + seconds(2) + millisec(1));

The DateTime library has a ptime class for specifying accurate time intervals. Times can be specified to the nearest nanosecond. Obviously most software can't support this accuracy directly, but the library can work with hardware clocks to enforce this accuracy.

Page 159: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 159

Copyright ©1994-2010 CRS Enterprises 159

Time Iterators• time_iterator(start_time, increment)

time_iterator iterator(now, hours(1))time_iterator iterator(now, hours(1))

for(time_iterator iterator (now, hours(1)); iterator < tommorrow_start; ++iterator )

{cout << *iterator << endl;

}

for(time_iterator iterator (now, hours(1)); iterator < tommorrow_start; ++iterator )

{cout << *iterator << endl;

}

every hour

Time periods can be traversed with a time_iterator. The above iterator starts counting a "now" and continues in steps of 1 hour until a suitable stopping time is reached.

Page 160: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 160

Page 161: C++ Ericson Seminarseddon-software/C++/C++ Ericsson Seminar.pdf · C++ Seminar for Ericsson ©1994-2012 CRS Enterprises Ltd 1 Chris Seddon seddon-software@keme.co.uk Ericsson C++

C++ Seminar for Ericsson

©1994-2012 CRS Enterprises Ltd 161