Использование библиотеки
Download
1 / 24

Колотаев А. В. - PowerPoint PPT Presentation


  • 166 Views
  • Uploaded on

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

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Колотаев А. В.' - zinna


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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

Использование библиотеки Boost.Mpl

для построения программной архитектуры

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


Содержание

  • Краткий обзор библиотеки Boost.Mpl

    • Понятие метафункции, placeholder expression, лямбда-выражение

    • Средства Boost.Mpl: последовательности (mpl::vector, mpl::list), алгоритмы (mpl::fold), виды (mpl::joint_view, mpl::filter_view)

  • Использование Boost.Mpl

    • Описание проекта

    • Поддержка приема CRTP

    • Реализация паттерна Состояние


Boost mpl
Библиотека Boost.Mpl

Доступна по адресу www.boost.org\libs\mpl\index.html


Метафункция

Def.Класс или шаблон класса с публично доступным типом-членом type.

template <class T>

struct add_pointer

{

typedef T * type;

};

Вызов:

typedef add_pointer<int>::type pInt; // pInt == int*


Специализация метафункции

Первичный шаблон, предоставленный разработчиком библиотеки:

template <class T>

struct func

{

typedef generic_implementationtype;

};

Специализация пользователем библиотеки для своего типа:

template <class Y, class Z>

struct func<MyClass<Y,Z> >

{

typedef specialisation_for_my_classtype;

};


Tag dispatching
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;

};


Класс метафункции

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);


Placeholder expression
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;

Легкая интеграция метапрограмм и существующих шаблонов


Лямбда-выражения

Def.Лямбда-выражение – это метаданные, которые могут быть вызваны при помощи mpl::apply.

Формы лямбда-выражения

  • Класс метафункции

  • Placeholder expression


Последовательности

  • Произвольного доступа

    • 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));


Mpl fold

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

{};


Задание цепочки действий

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.


Views
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*>


Curiously recurring template pattern
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); }

};


Inherit crtp
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

{/*...*/};


«Вложенные» цепочки базовых классов

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>

> {};


Класс конфигурации классов

Агрегирует параметры компоненты. Базовые классы для получения связанных типов обращаются в класс конфигурации компоненты.

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

Для того, чтобы в наследнике можно было переопределить некоторые метаданные, они должны быть представлены в виде лямбда-выражений, принимающих параметром класс конфигурации.


Fsm mpl book
Пример: классов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


Пример: классов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 >

// +---------+-------------+---------+---------------------+

> {};

};


State pattern
Использование реализованного классов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;


State pattern1
Использование реализованного классов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;

};


State pattern2
Использование реализованного классов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>

> {};


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


Возможности данной реализации паттерна

  • Независимость базовых классов, от того, являются ли они базовыми для класса состояния или основного объекта

  • Простая реализация вложенных состояний


ad