1 / 59

Modern C++ in practice

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

fynn
Download Presentation

Modern C++ in practice

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Modern C++ in practice Part 2

  2. Today Generic programming introduction Learn & code some generic design patterns

  3. 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

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

  5. 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?

  6. 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

  7. 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

  8. 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

  9. Why bother learning Larger design space => more sweetspots Encapsulate error prone code C++ 0x Different perspective Will spread to other languages

  10. Very simplified... OO programming builds on run-time polymorphism Generic programming builds on compile-time polymorphism

  11. 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(); }

  12. The STL Laid the foundation of generic programming in C++ Alexander Stepanov first introduced GP in Ada

  13. STL • Containers • Iterators • Algorithm • Functors

  14. Concepts • Valid expressions • Associated types • Invariants • Complexity guarantees Types which satifies requirements models the concept Concepts can be refined

  15. Surf time! Review iterator concepts at http://www.sgi.com/tech/stl/table_of_contents.html

  16. 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; }

  17. Memcpy generalized template <typename InputIterator, typename OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) { while (first != last) *result++ = *first++; return result; }

  18. Hack time! Implement www.sgi.com/tech/stl/find_if.html

  19. How to apply GP Apply at generic layers and architecture Don’t be overly specific Spread conventions

  20. Second part Get familiar with generic design techniques Introduce, code small example, surf APIs Time for a break?

  21. Object generators Use template type deduction to construct unnamed temporaries std::make_pair boost::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));

  22. Hack time! Implement make_shared_ptr

  23. Type traits Associates information with a compile time entity Non-intrusive templated class Uses partial template specialization Never instantiated

  24. Ehh... What the *beep*?

  25. Example usage template <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

  26. Example implementation template <typename T> struct is_void : public false_type{}; template <> struct is_void<void> : public true_type{};

  27. 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

  28. 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

  29. Tag dispatching Dispatch function calls depending of type properties Uses function overloading to do so Type traits class often provide tags

  30. Tag dispatching struct 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); }

  31. Tag dispatching Appears in STL & boost – important to know

  32. Curiously Recurring Template Pattern class Derived : public Base<Derived> Example class Y: public boost::enable_shared_from_this<Y>

  33. Hack time! Use CRTP implement an instance counter

  34. CRTP as abstract base class template <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

  35. 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

  36. 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”); } };

  37. 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”); } };

  38. 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 creation Thread safe or not Destroy or cache not used resources

  39. Policy classes Policy 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; };

  40. 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); };

  41. Policy based class design Extend interface, add state, add compile time entites Need not be entirely orthogonal Can pass policies on to internal subclasses Book tip: Modern C++ Design

  42. Break?

  43. Surf time! Let’s have a look at a policized class svn.boost.org/svn/boost/sandbox/flyweight/libs/flyweight/doc/

  44. Policies vs traits Type traits and policies are only instantiated as base-classes Neither type traits nor policy inheritance model IS-A Policies can add state, type traits doesn’t Policies can extend interfaces, type traits has no functions Type traits is pure, compile time, entity -> information mapping You can use type traits as policy parameters to model concepts

  45. SFINAE template<class IntType> IntType triple(IntType i) { return 3*i; } void foo() { triple(”hej!”); }

  46. 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) { ... }

  47. SFINAE If you ever need to limit a function template www.boost.org/libs/utility/enable_if.html

  48. Problem 1 Giving away too much information // Models Container class 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 }

  49. Problem 2 Requiring user code is templated template <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(); }

  50. Solution: Type Erasure class 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);

More Related