1 / 44

Higher order programming

Higher order programming. Using C++ and boost. C++ concepts. // T must model MyFuncConcept template<class T> generic_function(T t) { t.MyFunc(); }. C++ concepts. T is a model of MyFuncConcept if T has a member function called MyFunc which takes no arguments. C++ concepts.

niyati
Télécharger la présentation

Higher order programming

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. Higher order programming Using C++ and boost

  2. C++ concepts // T must model MyFuncConcept template<class T> generic_function(T t) { t.MyFunc(); }

  3. C++ concepts T is a model of MyFuncConcept if T has a member function called MyFunc which takes no arguments

  4. C++ concepts struct MyFuncClass { void MyFunc() {...} }; { MyFuncClass mfc; generic_function(mfc); // Compiles int i; generic_function(i); // Compilation error }

  5. C++ example concepts

  6. C++ concepts • An assumption about a type parameter • Compilation error if assumption fails • Language support for concepts will be added in C++0X template <DefaultConstructible T> ...

  7. Polymorphism through concepts Compile-time polymorphism through ”impicit interfaces” template<class T> void foo(T& t) { ... t.bar(); ... } Run-time polymorphism through explicit interfaces class FooType { virtual void bar() = 0; }; void foo(FooType& t) { ... t.bar(); ... }

  8. Sidenote: boost::concept_check • Provide easy to read compilation errors • Earlier compilation errors • Helps writing understandable code

  9. boost::concept_check example template <class RandomAccessIter> void stable_sort(RandomAccessIter first, RandomAccessIter last) { using namespace boost; function_requires< RandomAccessIteratorConcept<RandomAccessIter> >(); typedef typename std::iterator_traits<RandomAccessIter>::value_type value_type; function_requires< LessThanComparableConcept<value_type> >(); ... }

  10. Higher order programming Passing functions as values Having values requires a type

  11. C++ function pointers • Unintuitive syntax • Casting between member function pointers problematic • Pointers to virtual functions problematic • Different compilers behave differentally

  12. C++ concept of a functor A class which defines operator() struct SomeFunctor { void operator()() {...} }; template <class F> void foo(F f) { ... f(); ... }

  13. C++ concept of a functor Some STL algorithms also require internal typedefs for return_type, first_argument_type, second_argument_type struct SomeFunctor { typedef bool return_type; typedef int first_argument_type; bool operator()(int x) {...} };

  14. Hand made functor examples Can take various amounts of arguments struct MyNullaryFunctor { void operator()(); }; struct MyUnaryFunctor { void operator()(int arg1); };

  15. Hand made functor examples Can hold state struct NullaryFunctor { NullaryFunctor(int state); void operator()(); private: int iState; }; Some STL algorithms requires stateless functors

  16. Hand made functor examples Can return a value struct SomePredicate { bool operator(int i)(); };

  17. STL algorithm example template <class InputIterator, class Predicate> std::iterator_traits<InputIterator>::difference_type std::count_if(InputIterator first, InputIterator last, Predicate pred) • InputIterator is a model of the Input Iterator concept • Predicate is a model of the Predicate concept • InputIterator's value type is convertible to Predicate's argument type

  18. STL functor example namespace { struct MyPredicate { bool operator()(int i) const { return i>=0 && i<=9; } }; } { std::vector<int> vec = ...; unsigned int single_digits = std::count_if(vec.begin(), vec.end(), MyPredicate()); }

  19. boost::function Generalized callback through functors • Compatible with free functions, member functions and other functors • Abstracts away callback type • Intuitive semantics • Easy to read syntax

  20. boost::function example void free_func(int x); { boost::function<void(int x)> callback = free_func; callback(10); }

  21. boost::function example struct MyFunctor { void operator()(int x); }; { boost::function<void(int x)> callback = MyFunctor(); callback(10); }

  22. boost::function example struct MyClass { void member_func(int x); }; { // Need an instance to call a member function variable boost::function<void(MyClass*, int x)> callback = &MyClass::member_func; MyClass my_class; callback(&my_class, 10); }

  23. boost::function semantics { boost::function<void(int x)> callback; // unitialized ... if (callback) callback(10); }

  24. boost::function usage example class OkCancelDialog { OkCancelDialog(const boost::function<void()>& onOk, const boost::function<void()>& onCancel); };

  25. Recall from RAII presentation prepare_something(); possibly_throwing_call_1(); possibly_throwing_call_2(); rollback_preparation(); rollback_call_1();

  26. Recall from RAII presentation prepare_something(); try { possibly_throwing_call_1(); try { possibly_throwing_call_2(); } catch (...) { rollback_call_1(); rollback_preparation(); throw; } } catch (...) { rollback_preparation(); throw; }

  27. Recall from RAII presentation • Error-prone to write • Difficult to read • Difficult to change • Poor scalability

  28. Recall from RAII presentation class ScopeGuard { ScopeGuard(const boost::function<void()>& rollback) : mRollBack(rollback) {} ~ScopeGuard() { if (mRollBack) mRollBack(); } void Dismiss() { mRollback = boost::function<void()>(); } private: boost::function<void()> mRollback; };

  29. Recall from RAII presentation prepare_something(); ScopeGuard preparation_guard(rollback_preparation); possibly_throwing_call_1(); ScopeGuard call_1_guard(rollback_call_1); possibly_throwing_call_2(); // Commit preparation_guard.Dismiss(); call_1_guard.Dismiss();

  30. Writing custom made functors • Is boring • Generates a lot of code • Takes some time

  31. boost::bind Generates unnamed functors from: • Function pointers • Member function pointers • Other functors Meant to be used as unnamed temporaries

  32. boost::bind example void foo (int arg1, int arg2, int arg3) { std::cout << arg1 << ” ” << arg2 << ” ” << arg3 << std::endl; } { boost::bind(foo, _1, _2, _3) (1, 2, 3); boost::bind(foo, _3, _2, _1) (1, 2, 3); boost::bind(foo, _1, _1, _1) (20); boost::bind(foo, _3, _3, _3) (10, 20, 30); boost::bind(foo, 1, 2, 3) (); boost::bind(foo, 1, _1, 1) (1, 2, 3); }

  33. boost::bind, what’s happening? void foo (int arg1, int arg2, int arg3); boost::bind(foo, 10, _1, 30); What’s the return type of the bind expression? struct some_super_strange_type_with_loads_of_templates { void operator(int x) { foo(iArg1, x, iArg3); } int iArg1, iArg3; };

  34. boost::bind example namespace { bool my_pred (int i) { return i>=0 && i<=9; } } { std::vector<int> vec = ...; unsigned int single_digits = std::count_if(vec.begin(), vec.end(), boost::bind(my_pred, _1)); }

  35. boost::bind logical operators { std::vector<int> vec = ...; unsigned int single_digits = std::count_if(vec.begin(), vec.end(), _1>=0 && _1<=9); }

  36. boost::bind member functions struct X { void SomeFunc(int arg1, int arg2); }; { std::vector<X> vec; std::for_each(vec.begin(), vec.end(), boost::bind(&X::SomeFunc, _1, 1, 2)); }

  37. boost::bind nested expressions std::string f(std::string const & x) { return "f(" + x + ")"; } std::string g(std::string const & x) { return "g(" + x + ")"; } std::string h(std::string const & x, std::string const & y) { return "h(" + x + ", " + y + ")"; } std::string k() { return "k()"; } template<class F> void test(F f) { std::cout << f("x", "y") << '\n'; } { using namespace boost; test( bind(f, bind(g, _1)) ); test( bind(f, bind(h, _1, _2)) ); test( bind(h, bind(f, _1), bind(g, _1)) ); test( bind(h, bind(f, _1), bind(g, _2)) ); test( bind(f, bind(k)) ); }

  38. boost::bind semantics Bound values are stored by value! struct some_super_strange_type_with_loads_of_templates { void operator(int x) { foo(iArg1, x, iArg3); } int iArg1, iArg3; };

  39. boost::bind references void foo(const X& arg); { X x; boost::bind(foo, boost::cref(x))(); }

  40. boost::bind and shared_ptr struct X { void foo() {} }; { boost::shared_ptr<X> x; boost::bind(&X::foo, x)(); }

  41. bind&function usage Bind • Pass as unnamed temporaries for templated functions • Bind arguments as state • Specifically bind instances to member functions • Reorder arguments Function • Pass as arguments for non-templated functions • Abstracts away function type • Store as non-templated variables • Can be uninitialized

  42. Combining bind and function function and bind both model the functor concept Both are compatible with other functors void func(int arg1); { boost::function<void()> call = boost::bind(func, 1000); }

  43. Combining bind and function // Non-templated higher order function void register_callback(boost::function<void()> callback); void my_callback(int source); { register_callback(boost::bind(&my_callback, 10)); }

  44. Boost lambda Similar to bind, larger and more advanced library Pushes the limits of the C++ language using namespace boost; std::vector<int> v = ...; std::for_each(v.begin(), v.end(), if_(_1 % 2 == 0)[ cout << _1 ]); int a[5][10]; int i; std::for_each(a, a+5, for_loop(var(i)=0, var(i)<10, ++var(i), _1[var(i)] += 1)); std::for_each(v.begin(), v.end(), ( switch_statement( _1, case_statement<0>(std::cout << constant("zero")), case_statement<1>(std::cout << constant("one")), default_statement(cout << constant("other: ") << _1) ), cout << constant("\n") ) );

More Related