1 / 24

Колотаев А. В.

Использование библиотеки Boost.Mpl для построения программной архитектуры. Колотаев А. В. Содержание. Краткий обзор библиотеки Boost.Mpl Понятие метафункции, placeholder expression, лямбда-выражение

zinna
Download Presentation

Колотаев А. В.

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. Использование библиотеки Boost.Mpl для построения программной архитектуры Колотаев А. В.

  2. Содержание • Краткий обзор библиотеки Boost.Mpl • Понятие метафункции, placeholder expression, лямбда-выражение • Средства Boost.Mpl: последовательности (mpl::vector, mpl::list), алгоритмы (mpl::fold), виды (mpl::joint_view, mpl::filter_view) • Использование Boost.Mpl • Описание проекта • Поддержка приема CRTP • Реализация паттерна Состояние

  3. Библиотека Boost.Mpl Доступна по адресу www.boost.org\libs\mpl\index.html

  4. Метафункция Def.Класс или шаблон класса с публично доступным типом-членом type. template <class T> struct add_pointer { typedef T * type; }; Вызов: typedef add_pointer<int>::type pInt; // pInt == int*

  5. Специализация метафункции Первичный шаблон, предоставленный разработчиком библиотеки: template <class T> struct func { typedef generic_implementationtype; }; Специализация пользователем библиотеки для своего типа: template <class Y, class Z> struct func<MyClass<Y,Z> > { typedef specialisation_for_my_classtype; };

  6. Tag dispatching //--------------------------------------- library code template <class T> struct sequence_tag{ typedef typename T :: sequence_tag type; }; template <class T> struct library_func_impl; template <class T> struct library_func : library_func_impl<typename sequence_tag<T>::type> // ::type {}; //--------------------------------------- user code struct my_sequence_tag; struct MySequenceA{ typedef my_sequence_tag sequence_tag; /*...*/ }; struct MySequenceB{ typedef my_sequence_tag sequence_tag; /*...*/ }; template <> struct library_func_impl<my_sequence_tag> { typedef my_implementationtype; };

  7. Класс метафункции Def.Класс метафункции – класс или шаблон класса с публично доступной вложенной метафункцией apply. #include <boost/mpl/apply.hpp> namespace mpl= boost::mpl; struct add_pointer_f{ template <class T> struct apply: add_pointer<T> {}; }; template <class Func, class T> struct twice// twice(Func, T) == Func(Func(T)) : mpl::apply<Func, typename mpl::apply<Func, T>::type> {}; int **p = twice<add_pointer_f, int>::type(0);

  8. Placeholder expression Def. Placeholderexpression –это либо заместитель, либо специализация шаблона класса, у которого хотя бы один аргумент placeholder expression. #include <boost/mpl/placeholders.hpp> using namespace mpl::placeholders; typedef twice<add_pointer_f, _1> add_pointer_twice; int **p = mpl::apply<add_pointer_twice, int>::type(0); Позволяет формировать новые метафункции, связывая с параметрами существующих метафункций некоторые значения Позволяет формировать новые метафункции как композицию существующих метафункций Превращение обычных шаблонов классов в placeholder expression typedef mpl::apply<std::vector<_>, T>::type vector_of_T; Легкая интеграция метапрограмм и существующих шаблонов

  9. Лямбда-выражения Def.Лямбда-выражение – это метаданные, которые могут быть вызваны при помощи mpl::apply. Формы лямбда-выражения • Класс метафункции • Placeholder expression

  10. Последовательности • Произвольного доступа • mpl::vector, mpl::deque, • Однонаправленные • mpl::list • Ассоциативные • mpl::map, mpl::set typedef mpl::vector<int, char, short, long, float, double> types; // найти положение long в types typedef mpl::find<types, long>::typelong_pos; // разыменовать итератор typedef mpl::deref<long_pos>::typex; // проверяем, что получили ожидаемый результат BOOST_STATIC_ASSERT((boost::is_same<x,long>::value));

  11. empty_base A inherit_2<…, ….> B C inherit_2<…, ….> D inherit_2<…, ….> inherit_2<…, ….> X Алгоритм mpl::fold struct A{}; struct B{}; struct C{}; struct D{}; struct bases_for_X: mpl::vector<A,B,C,D> {}; template <class First, class Second> struct inherit_2: First, Second {}; struct X : mpl::fold< bases_for_X, mpl::empty_base, inherit_2<_, _> >::type {};

  12. Задание цепочки действий struct empty_updator{ void update(double){} }; template <class Tail, class Head> struct inherit_and_define_update: Tail, Head { void update(double time) { Tail::update(time); Head::update(time); } }; struct X: mpl::fold<bases_for_X, empty_updator, inherit_and_define_update<_, _> >::type {}; Вызов X::update сведется к вызову A::update, B::update, C::update, D::update.

  13. Views – адаптеры последовательностей • «Ленивые» • Неизменяемые struct bases_for_X : mpl::joint_view<mpl::vector<A,B>, mpl::vector<C,D> > {};// bases_for_X ~ mpl::vector<A,B,C,D> struct filtered_bases : mpl::filter_view<bases_for_X, boost::is_same<_, A> > {};// filtered_bases ~ mpl::vector<A> struct transformed: mpl::transform_view<bases_for_X, add_pointer<_> > {};// transformed ~ mpl::vector<A*,B*,C*,D*>

  14. Curiously Recurring Template Pattern Def. Наследование класса X от специализации шаблона класса, принимающей аргументом класс X. struct X: base<X> { /*...*/ }; Доступ из базового класса к членам наследника осуществляется при помощи указателя this, приведенного к типу указателя на наследник. template <class Derived> struct BaseA { void method1() { self().baseB().method2(); } BaseA & baseA() { return *this; } private: Derived& self() { return static_cast<Derived&>(*this); } };

  15. inherit_crtp struct MyComponent : BaseA<MyComponent> , BaseB<MyComponent, ParamForB> , BaseC<MyComponent> { /*...*/ }; При таком подходе список базовых классов (BaseA<…>, BaseB<…>, BaseC<…>)трудно использовать в качестве базовых для другой компоненты. struct bases : mpl::vector<BaseA<_>, BaseB<_,ParamForB>, BaseC<_> > {}; struct MyComponent : inherit_crtp<bases, MyComponent>::type {/*...*/};

  16. «Вложенные» цепочки базовых классов struct damage_listeners: mpl::vector< HitPoints<_>, SmokeEmitter<_>, HitPrints<_> > {}; struct actions: mpl::vector< CheckValidPosition<_>, ProcessTargets<_>, UpdatePosition<_> > {}; struct bases: mpl::vector< BaseA<_>, OnDamage<_, damage_listeners>, OnUpdate<_, actions> > {};

  17. Класс конфигурации Агрегирует параметры компоненты. Базовые классы для получения связанных типов обращаются в класс конфигурации компоненты. Классы конфигурации удобно наследовать друг от друга. Списки базовых классов объединяются, например, при помощи mpl::joint_view. Для того, чтобы в наследнике можно было переопределить некоторые метаданные, они должны быть представлены в виде лямбда-выражений, принимающих параметром класс конфигурации.

  18. Пример: FSM (из Mpl Book) // concrete FSM implementation class player : public state_machine<player> { private: // the list of FSM states enum states { Empty, Open, Stopped, Playing, Paused , initial_state = Empty }; // transition actions void start_playback(play const&); void open_drawer(open_close const&); void close_drawer(open_ close const&); void store_cd_info(cd_detected const&); void stop_playback(stop const&); void pause_playback(pause const&); void resume_playback(play const&); void stop_and_open(open_close const&); // continued on the next page

  19. Пример: FSM (продолжение) // transition actions friend class state_machine<player>; typedef player p; // makes transition table cleaner // transition table struct transition_table : mpl::vector11< // Start Event Next Action // +---------+-------------+---------+---------------------+ row < Stopped , play , Playing , &p::start_playback >, row < Stopped , open_close , Open , &p::open_drawer >, // +---------+-------------+---------+---------------------+ row < Open , open_close , Empty , &p::close_drawer >, // +---------+-------------+---------+---------------------+ row < Empty , open_close , Open , &p::open_drawer >, row < Empty , cd_detected , Stopped , &p::store_cd_info >, // +---------+-------------+---------+---------------------+ row < Playing , stop , Stopped , &p::stop_playback >, row < Playing , pause , Paused , &p::pause_playback >, row < Playing , open_close , Open , &p::stop_and_open >, // +---------+-------------+---------+---------------------+ row < Paused , play , Playing , &p::resume_playback >, row < Paused , stop , Stopped , &p::stop_playback >, row < Paused , open_close , Open , &p::stop_and_open > // +---------+-------------+---------+---------------------+ > {}; };

  20. Использование реализованного State Pattern struct boat_cfg { struct states { // Идентификаторы состояний enum Id{ ACTIVE, HIDING, HIDDEN, APPEARING}; // События, инициирующие переходы // self().processAction(actions::Appear()); struct actions{ struct Appear{}; struct Hide{}; struct Leave{}; }; // базовые классы интерфейса абстрактного состояния struct bases: mpl::vector<update_base, collision_type_base> {}; // прокси-классы struct proxies: mpl::vector< proxy::PositionHolder<__>, proxy::MustHave <__>, proxy::ExplosionMaker<__> > {}; // интерфейс абстрактного состояния struct IState<__> base_type;

  21. Использование реализованного State Pattern // описание состояния struct active { const static Id ID = ACTIVE; // метафункция, позволяющая описание состояния переопределять в //наследникахTHE_STATE_IS_OVERRIDABLE(active) template <class T> struct apply { typedef typename T:: states:: activetype; }; // базовые классы конкретного состояния struct bases: mpl::vector< CollisionTypeRobotGround<__>, Active<__> > {}; // класс конкретного состояния typedef State<__, active> state_type; };

  22. Использование реализованного State Pattern struct hiding{ /*...*/ }; struct hidden{ /*...*/ }; struct appearing{ /*...*/ }; // начальное состояние typedef hiddeninitial; // таблица переходов struct Transitions: mpl::vector< fsm::row<hidden, actions::Appear, appearing>, fsm::row<appearing, actions::Leave, active>, fsm::row<active, actions::Hide, hiding>, fsm::row<hiding, actions::Leave, hidden> > {};

  23. Диаграмма сгенерированного конкретного состояния

  24. Возможности данной реализации паттерна • Независимость базовых классов, от того, являются ли они базовыми для класса состояния или основного объекта • Простая реализация вложенных состояний

More Related