modern c++ in practice

59
Modern C++ in practice Part 2

Upload: fynn

Post on 29-Jan-2016

104 views

Category:

Documents


3 download

DESCRIPTION

Modern C++ in practice. Part 2. Today. Generic programming introduction Learn & code some generic design patterns. Goals. Practical experience of C++ best practices, idioms and details Design patterns in C++ Generic, functional and template programming Using boost and STL - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Modern C++ in practice

Modern C++ in practicePart 2

johant
En introduktion till några väldigt andvändbara bibliotek.Även C++, generic programming och STL.Bitvis mycket tekniska detaljer - avbryt och fråga!Tänkt som diskussionKom gärna förbi mig och fråga saker
Page 2: Modern C++ in practice

Today

Generic programming introductionLearn & code some generic design patterns

Page 3: Modern C++ in practice

Goals

Practical experience of

•C++ best practices, idioms and details•Design patterns in C++•Generic, functional and template programming•Using boost and STL•Utilize APIs, books and mailing lists

Coherent coding style and get to know each other

Page 4: Modern C++ in practice

Past•RAII•Boost candy•Higher order programming•Workshops, variant+signals

johant
smart_ptrsoptionalassign
johant
RAAIRelation till shared_ptrScopeGuard
johant
Concept, function och bind
johant
designade leksaksspel. slots n'signals. mest variant
johant
summerbreak + p4evo
Page 5: Modern C++ in practice

Future•Modelling static or dynamic?•”Prepone” error detection•Template metaprogramming introduction•Working with namespaces•Free functions over classes•Exception safe code•Event driven architecture•Dive deeper: boost, STL, template metaprogramming, generic programming•Something else?

Page 6: Modern C++ in practice

C++ - a multiparadigm language•Procedural programming•Object oriented programming•Generic programming•Functional programming•Embedded DSLs•Template metaprogramming•Macro metaprogramming

Know and blend these paradigms Generic programming is especially important

johant
huge edsign space. fruitful to know basics.använda en programmeringsparadigm som liger nära problemområdet. mindre kod, mindre komplext
johant
föredra fria funktioner när inget tillstånd inblandat
johant
small subset of generic programming
johant
slippa korsa språkgränser. debuggervikten av att jobba i språk nära problemområdetkraften av deklarativa språkexempel: boost xpressive, statechart, lambda.till viss mån gränsar boost bind
johant
support generic programming. true variadiac parameter list.in situations you need to generate code. better withing language, especially for libs
Page 7: Modern C++ in practice

OO is just one paradigm

”I find OOP methodologically wrong”Alexander Stepanov

”Objects are a poor man’s closures”Norman Adams

”... what society overwhelmingly asks for is snake oil. Of course, the snake oil has the most impressive names —otherwise you would be selling nothing— like ... "Object Orientation" ...”

Edsger W. Dijkstra

Page 8: Modern C++ in practice

What is generic programming•Orthogonality•Encapsulate the essence of a problem•Very high degree of reusability

”Commit to abstractions, not to details: Use the mose generic and abstract means to implement a piece of functionality”

C++ coding standards #67

johant
Differs from language to language
Page 9: Modern C++ in practice

Why bother learning

Larger design space => more sweetspotsEncapsulate error prone codeC++ 0xDifferent perspectiveWill spread to other languages

johant
Not only to catch errors. p4 evo: Easy to setup listener/like structures with signals/slots. Easier to asynchronous calls make. Would it shorter turnaround times for unit tests (almost 5min setup, 30s to get feedback)you get more agile
Page 10: Modern C++ in practice

Very simplified...

OO programming builds on run-time polymorphismGeneric programming builds on compile-time polymorphism

Page 11: Modern C++ in practice

Polymorphism revisited

Run-time polymorphism through explicit interfaces

class FooType { virtual void bar() = 0; };

void foo(FooType& t) { t.bar(); }

Compile-time polymorphism through ”implicit interfaces”

template<class T>

void foo(T& t) { t.bar(); }

johant
decision of which function to call is made at either compile time or run-time
Page 12: Modern C++ in practice

The STL

Laid the foundation of generic programming in C++

Alexander Stepanov first introduced GP in Ada

johant
started working on generic programming 1979
Page 13: Modern C++ in practice

STL•Containers•Iterators•Algorithm•Functors

Page 14: Modern C++ in practice

Concepts•Valid expressions•Associated types•Invariants•Complexity guarantees

Types which satifies requirements models the conceptConcepts can be refined

Page 15: Modern C++ in practice

Surf time!

Review iterator concepts at

http://www.sgi.com/tech/stl/table_of_contents.html

Page 16: Modern C++ in practice

Hack time!

Generalize memcpy

void* memcpy(void* region1, const void* region2, size_t n)

{

const char* first = (const char*)region2;

const char* last = ((const char*)region2) + n;

char* result = (char*)region1;

while (first != last) *result++ = *first++;

return result;

}

Page 17: Modern C++ in practice

Memcpy generalizedtemplate <typename InputIterator, typename OutputIterator>

OutputIterator copy(InputIterator first, InputIterator last,

OutputIterator result)

{

while (first != last) *result++ = *first++;

return result;

}

Page 18: Modern C++ in practice

Hack time!

Implement

www.sgi.com/tech/stl/find_if.html

Page 19: Modern C++ in practice

How to apply GP

Apply at generic layers and architectureDon’t be overly specificSpread conventions

Page 20: Modern C++ in practice

Second part

Get familiar with generic design techniques

Introduce, code small example, surf APIs

Time for a break?

Page 21: Modern C++ in practice

Object generatorsUse template type deduction to construct unnamed temporaries

std::make_pairboost::bind

template <class T> foo(T t);

foo(std::pair<unsigned int, std::multimap<unsigned int, std::string> >(0, it));

foo(std::make_pair(0,it));

Page 22: Modern C++ in practice

Hack time!

Implement make_shared_ptr

Page 23: Modern C++ in practice

Type traits

Associates information with a compile time entity

Non-intrusive templated classUses partial template specializationNever instantiated

Page 24: Modern C++ in practice

Ehh...What the *beep*?

Page 25: Modern C++ in practice

Example usagetemplate <class Iterator> struct iterator_traits { typedef typename Iterator::value_type value_type;

typedef typename Iterator::difference_type difference_type; ... Some other things

};

template<class Iterator>void my_algorithm(Iterator begin, Iterator end){... iterator_traits<Iterator>::value_type copy_of_first_element = *begin;...}

To write your own iterator•Specialize std::iterator_traits•Or provide the required typedefs

Page 26: Modern C++ in practice

Example implementationtemplate <typename T>

struct is_void : public false_type{};

template <>

struct is_void<void> : public true_type{};

Page 27: Modern C++ in practice

Surf time!

Let’s have a look at some usages of type traits

www.boost.org/doc/html/boost_typetraits/examples.html

Then let’s look at what boost::type_traits contains

www.boost.org/doc/html/boost_typetraits/category.html

Page 28: Modern C++ in practice

Hack time!template <class Iterator> struct iterator_traits {

typedef typename Iterator::iterator_category iterator_category; typedef typename Iterator::value_type value_type; typedef typename Iterator::difference_type difference_type; typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference;

};

Implement raw pointer specialization of iterator_traits

johant
Preferably by
Page 29: Modern C++ in practice

Tag dispatching

Dispatch function calls depending of type properties

Uses function overloading to do so

Type traits class often provide tags

Page 30: Modern C++ in practice

Tag dispatchingstruct input_iterator_tag{};

struct random_access_iterator_tag{};

namespace detail {

template<class InputIterator, class Distance>

void advance_impl(InputIterator& i, Distance n, input_iterator_tag) {...}

template<class RandomAccessIterator, class Distance>

void advance_impl(RandomAccessIterator & i, Distance n,

random_access_iterator_tag) {...}

}

template<class InputIterator, class Distance>

void advance(InputIterator& i, Distance n)

{

typedef typename iterator_traits<InputIterator>::iterator_category category;

detail::advance_impl(i, n, category);

}

johant
Jag misstänker att ni inte behöver implementera, bara använda er av detta till att börja med - så vi skippar implementationssteget
Page 31: Modern C++ in practice

Tag dispatching

Appears in STL & boost – important to know

Page 32: Modern C++ in practice

Curiously Recurring Template Patternclass Derived : public Base<Derived>

Example

class Y: public boost::enable_shared_from_this<Y>

Page 33: Modern C++ in practice

Hack time!

Use CRTP implement an instance counter

johant
non intrusive
Page 34: Modern C++ in practice

CRTP as abstract base classtemplate <class Derived> struct Base { void interface() { .. static_cast<Derived&>(*this).implementation(); ... } };

struct Derived : public Base<Derived> {

void implementation();};

Derived needn’t implement an interface, only model a concept

Page 35: Modern C++ in practice

Policy based class design

Reminds you of aspect oriented development

Break classes down to small orthogonal pieces

Encapsulate a design space, allow users to do the trade offs

Page 36: Modern C++ in practice

Policy example

struct ThrowError { void handle_error(int line_nr, const std::string& s) { throw std::exception(s); }};

struct AssertError { void handle_error(int line_nr, const std::string& s) { assert(false); }};

struct LogError { void handle_error(int line_nr, const std::string& s) { log(s); }};

struct IgnoreError { void handle_error(int line_nr, const std::string& s) {}};

template <class ErrorHandlingModel=LogError>class Foo : public ErrorHandlingModel{ void bar() { if (condition_xxx) handle_error(__LINE__, ”Error, XXX occurred”); }};

johant
Easliy make a composite ErrorHandlingModel
Page 37: Modern C++ in practice

Policy example

struct MultiThreadedModel {protected: typedef boost::thread::mutex mutex; mutex m_mutex;};

struct SingleThreadedModel {protected: struct mutex { // Dummy class struct scoped_lock { scoped_lock(mutex) {} }; }; mutex m_mutex;};

template <class ErrorHandlingModel, class ThreadingModel>class Foo : public ErrorHandlingModel { void bar() { typename ThreadingModel::mutex::scoped_lock lock(m_mutex); if (condition_xxx) handle_error(__LINE__, ”Error, XXX occurred”); }};

Page 38: Modern C++ in practice

Hack time!template<class ValueType,

class ValueDescription,

class ThreadingModel,

class LifeTimeModel>

class Cache

{

boost::shared_ptr<ValueType> get(const ValueDescription& description);

};

Use new ValueType(ValueDescription) for creationThread safe or notDestroy or cache not used resources

Page 39: Modern C++ in practice

Policy classesPolicy classes can also be used to extend interfaces

How would you change the following class to allow asynchronous delivery?

class MessageChannel

{

template<class Msg>

void send(const Msg& msg) const;

template<class Msg>

const Signal<void(const Msg&)>& get_signal() const;

};

johant
Note how our signal class is re-used for registering/removing listeners. There should never be a need to reimplement this.
Page 40: Modern C++ in practice

Hack time!template<class T> struct ImmediateDeliveryModel {protected: template <class Msg> void on_message(const Msg& msg);};

template<class T> class RequestedDeliveryModel {public: void deliver();protected: template<class Msg> void on_message(const Msg& msg);};

template <template <class> DeliveryModel>class MessageChannel : public DeliveryModel<MessageChannel> // CRTP{public: template<class Msg> void send(const Msg& msg) { on_message(msg); }protected: template<class Msg> void deliver_impl(const Msg& msg);};

Page 41: Modern C++ in practice

Policy based class design

Extend interface, add state, add compile time entitesNeed not be entirely orthogonalCan pass policies on to internal subclasses

Book tip: Modern C++ Design

johant
Can still be useful
johant
Good rule of thumb. Don't be unnecessarily specific
johant
The book that introduced policiesSimilar constructs were already used in STLDiscuesses guide lines on using policies
johant
Document your policies publicly as concepts and let users provide their own
Page 42: Modern C++ in practice

Break?

Page 43: Modern C++ in practice

Surf time!

Let’s have a look at a policized class

svn.boost.org/svn/boost/sandbox/flyweight/libs/flyweight/doc/

Page 44: Modern C++ in practice

Policies vs traitsType traits and policies are only instantiated as base-classesNeither type traits nor policy inheritance model IS-A

Policies can add state, type traits doesn’tPolicies can extend interfaces, type traits has no functions

Type traits is pure, compile time, entity -> information mappingYou can use type traits as policy parameters to model concepts

Page 45: Modern C++ in practice

SFINAE

template<class IntType>

IntType triple(IntType i)

{ return 3*i; }

void foo()

{

triple(”hej!”);

}

Page 46: Modern C++ in practice

SFINAE

Substitution Failure Is Not An Error

template<bool, typename T = void>

struct enable_if {};

template<typename T>

struct enable_if<true, T> { typedef T type; };

template<class T>

enable_if<is_integral<T>::type, T>::type

triple(T t) { ... }

Page 47: Modern C++ in practice

SFINAE

If you ever need to limit a function template

www.boost.org/libs/utility/enable_if.html

Page 48: Modern C++ in practice

Problem 1 Giving away too much information// Models Containerclass MyClass{private: typedef std::vector<int> InternalCollection; public: typedef InternalCollection::iterator iterator; ...};

void user_code(){ MyClass a; int size = a.end() – a.begin(); // compiles cleanly, violates

promises}

Page 49: Modern C++ in practice

Problem 2 Requiring user code is templatedtemplate <class T> class Foo { Foo(const T& t); void bar(); void baz();

void monkey(T t);};

template <class T> void user_code(Foo<T>& foo){ foo.bar(); foo.baz();}

johant
multiple problems with thisAll code reside in header files -> compiler dependencies increase
Page 50: Modern C++ in practice

Solution: Type Erasureclass Foo { virtual void bar() = 0; virtual void baz() = 0;};

template <class T> class FooImpl : public Foo{ Foo(const T& t);

void bar(); void baz();

void monkey(T t);};

void user_code(Foo& foo);

Page 51: Modern C++ in practice

Solution to problem 1

template< class Value,

class CategoryOrTraversal,

class Reference = Value&,

class Difference = std::ptrdiff_t >

class any_iterator;

Page 52: Modern C++ in practice

Hack time!

Implement void_function

•Compatible with free functions•Compatible with other functors•Provide uniform type

Erase which type it was constructed from

Page 53: Modern C++ in practice

Problems with concepts

Until C++0x comes, we have the following problems

•Incorrect arguments generate difficult error messages•The documented requirements might not cover everything•Code and documentation might drift out of sync

Page 54: Modern C++ in practice

Reminder

The Boost Concept Checking Library provides:

•A mechanism for inserting compile-time checks•A framework for specifying concept requirements•A mechanism for verifying concept coverage•Concept checking and archetype classes for STL concepts

Concept checks to help code usersArchetype checks to help require correct concepts

Page 55: Modern C++ in practice

Surf time!

Let’s refresh our memory

www.boost.org/libs/concept_check/using_concept_check.htm

Page 56: Modern C++ in practice

A taste of Metaprogrammingtemplate <unsigned long N>struct binary{ static const unsigned long value = binary<N/10>::value*2 + N%10;};

template <>struct binary<0>{ static const unsigned long value = 0;};

binary<101>::value

johant
often hear, templates are a turing complete language.partial template specialization. naturally model recursion with a specific specialzation as stopping conditionIn this language we can model data structures, algorithms - whatever. this concept has been well studied and extended to a library similar to STL - MPL.
Page 57: Modern C++ in practice

Summary first part

C++ is a multiparadigm language

GP+OO can achieve simplified, robust, decoupled systems

Concepts consists of•Invariants•Valid expressions•Associated types•Complexity guarantees

Page 58: Modern C++ in practice

Summary second partQuick taste of some patterns

•Object generators•Type traits•Tag dispatching•CRTP•Policy classes•SFINAE•Type erasure•Concept checking

Get familiar with, not master

Page 59: Modern C++ in practice

Thanks for listening

Slides available at

twiki.gameop.net/twiki/bin/view/Main/ModernC++InPractice