SlideShare a Scribd company logo
1 of 74
Download to read offline
Метапрограммирование:
Строим конечный автомат
offline
online
connect
connecting
connected
connection failed
idle
transaction
begin
commit rollback
disconnected
tran idle
simple mode extended mode
exec exec prepared
Конечный автомат - что это?
DSL для конечного автомата
Реализация DSL
Где можно применить?
5
О чём поговорим
Конечный автомат - что это?
Конечный автомат – абстрактный автомат, число
внутренних состояний которого конечно.
7https://ru.wikipedia.org/wiki/Конечный_автомат
Определение из
Википедии
M = (V, Q, q0, F, δ)
//*[sS]*?*/|([^:]|^)//.*$/gm
statement

: 'if' paren_expr statement

| 'if' paren_expr statement 'else' statement

| 'while' paren_expr statement

| 'do' statement 'while' paren_expr ';'

| '{' statement* '}'

| expr ';'

| ';'

;
8
Как выглядит?
9
Простейший КА на примере АК
ready
fire
pull / emit bullet
release
t
ullet
release
tick / emit bullet
12
Условные переходы
Sergei Fedorov | November 10, 2019
ready
pull / emit bullet
release
empty
reload
[depleted][!depleted]
[depleted]
fire
tick / emit bullet [!depleted]
14
Ортогональные состояния
AK47
Sergei Fedorov | November 10, 2019
Trigger
Machine gun
Safety lock
safe
auto
single
down
down [!firing]
up [!firing]
up [!firing]
ready
pull / emit bullet
release
empty
reload
[depleted][!depleted]
[depleted]
fire
tick / emit bullet [auto && !depleted]
15
Табличное представление
State Event Next State Action Condition (guard)
trigger
initial - ready !depleted
initial - empty depleted
empty reload ready change magazine
ready reload fire change magazine
ready pull the trigger fire emit bullet !safe
fire release the trigger ready
fire tick fire emit bullet automatic && !depleted
fire - empty depleted
selector
safe lever down automatic
automatic lever up safe !firing
automatic lever down single !firing
single lever up automatic !firing
DSL для конечного автомата
Машина состояний (state machine)
Таблица переходов (transition table)
Переход (transition)
Событие (event)
Состояние (state)
Действие (action)
при входе в состояние (on entry)
при выходе из состояния (on exit)
при переходе (transition action)
Условие перехода (transition guard)
17
Основные
сущности
Машина состояний (state machine)
Таблица переходов (transition table)
Переход (transition)
Событие (event)
Состояние (state)
Действие (action)
при входе в состояние (on entry)
при выходе из состояния (on exit)
при переходе (transition action)
Условие перехода (transition guard)
18
Основные
сущности
19
КА с ортогональными состояниями
struct machine_gun_def : afsm::def::state_machine<machine_gun_def> {
//@{
/** @name Sub-machines */
struct selector;
struct trigger;
using orthogonal_regions = type_tuple<trigger, selector>;
//@}
};
20
Табличное представление
State Event Next State Action Condition (guard)
trigger
initial - ready !depleted
initial - empty depleted
empty reload ready change magazine
ready reload fire change magazine
ready pull the trigger fire emit bullet !safe
fire release the trigger ready
fire tick fire emit bullet automatic && !depleted
fire - empty depleted
selector
safe lever down automatic
automatic lever up safe !firing
automatic lever down single !firing
single lever up automatic !firing
21
Табличное представление
State Event Next State Action Condition (guard)
trigger
initial - ready !depleted
initial - empty depleted
empty reload ready change magazine
ready reload fire change magazine
ready pull the trigger fire emit bullet !safe
fire release the trigger ready
fire tick fire emit bullet automatic && !depleted
fire - empty depleted
selector
safe lever down automatic
automatic lever up safe !firing
automatic lever down single !firing
single lever up automatic !firing
22
Машина состояний
struct selector : state_machine<selector> {
/** @name Selector substates */
struct safe;
struct single;
struct automatic;
using initial_state = safe;
// Type aliases to shorten the transition table
using down = events::safety_lever_down;
using up = events::safety_lever_up;
// selector transition table
using transitions = transition_table<
/* State | Event | Next | Action | Guard */
tr< safe , down , automatic , update_safety , none >,
tr< automatic , up , safe , update_safety , not_<firing> >,
tr< automatic , down , single , update_safety , not_<firing> >,
tr< single , up , automatic , update_safety , not_<firing> >
>;
};
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
Событие (event)
Состояние (state)
Действие (action)
при входе в состояние (on entry)
при выходе из состояния (on exit)
при переходе (transition action)
Условие перехода (transition guard)
33
Основные
сущности
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
Событие (event)
Состояние (state)
Действие (action)
при входе в состояние (on entry)
при выходе из состояния (on exit)
при переходе (transition action)
Условие перехода (transition guard)
34
Основные
сущности
35
Описание событий
namespace guns::events {
struct trigger_pull {};
struct trigger_release {};
struct reload {};
struct safety_lever_up {};
struct safety_lever_down {};
struct tick {
std::uint64_t frame = 0;
};
} // namespace guns::events
36
Описание событий
namespace guns::events {
struct trigger_pull {};
struct trigger_release {};
struct reload {};
struct safety_lever_up {};
struct safety_lever_down {};
struct tick {
std::uint64_t frame = 0;
};
} // namespace guns::events
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
✓Событие (event)
Состояние (state)
Действие (action)
при входе в состояние (on entry)
при выходе из состояния (on exit)
при переходе (transition action)
Условие перехода (transition guard)
37
Основные
сущности
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
✓Событие (event)
Состояние (state)
Действие (action)
при входе в состояние (on entry)
при выходе из состояния (on exit)
при переходе (transition action)
Условие перехода (transition guard)
38
Основные
сущности
39
Описание состояний
//@{
/** @name Selector substates */
struct safe : state<safe> {
static constexpr safety_lever lever = safety_lever::safe;
};
struct single : state<single> {
static constexpr safety_lever lever = safety_lever::single;
};
struct automatic : state<automatic> {
static constexpr safety_lever lever = safety_lever::automatic;
};
//@}
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
✓Событие (event)
✓Состояние (state)
Действие (action)
при входе в состояние (on entry)
при выходе из состояния (on exit)
при переходе (transition action)
Условие перехода (transition guard)
41
Основные
сущности
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
✓Событие (event)
✓Состояние (state)
Действие (action)
при входе в состояние (on entry)
при выходе из состояния (on exit)
при переходе (transition action)
Условие перехода (transition guard)
42
Основные
сущности
44
Действия при входе/выходе
struct empty : state<empty> {
template <typename FSM>
void
on_enter(afsm::none&&, FSM& fsm)
{
root_machine(fsm).ammo_depleted();
}
template <typename FSM>
void
on_exit(events::reload const&, FSM& fsm)
{
root_machine(fsm).ammo_replentished();
}
};
45
Действия при входе/выходе
struct empty : state<empty> {
template <typename FSM>
void
on_enter(afsm::none&&, FSM& fsm)
{
root_machine(fsm).ammo_depleted();
}
template <typename FSM>
void
on_exit(events::reload const&, FSM& fsm)
{
root_machine(fsm).ammo_replentished();
}
};
46
Действия при входе/выходе
struct empty : state<empty> {
template <typename FSM>
void
on_enter(afsm::none&&, FSM& fsm)
{
root_machine(fsm).ammo_depleted();
}
template <typename FSM>
void
on_exit(events::reload const&, FSM& fsm)
{
root_machine(fsm).ammo_replentished();
}
};
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
✓Событие (event)
✓Состояние (state)
Действие (action)
✓при входе в состояние (on entry)
✓при выходе из состояния (on exit)
при переходе (transition action)
Условие перехода (transition guard)
47
Основные
сущности
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
✓Событие (event)
✓Состояние (state)
Действие (action)
✓при входе в состояние (on entry)
✓при выходе из состояния (on exit)
при переходе (transition action)
Условие перехода (transition guard)
48
Основные
сущности
49
Действия при переходе
struct selector : state_machine<selector> {
/** @name Selector substates */
struct safe;
struct single;
struct automatic;
using initial_state = safe;
// Type aliases to shorten the transition table
using down = events::safety_lever_down;
using up = events::safety_lever_up;
// selector transition table
using transitions = transition_table<
/* State | Event | Next | Action | Guard */
tr< safe , down , automatic , update_safety , none >,
tr< automatic , up , safe , update_safety , not_<firing> >,
tr< automatic , down , single , update_safety , not_<firing> >,
tr< single , up , automatic , update_safety , not_<firing> >
>;
};
50
Действия при переходе
//@{
/** @name Selector substates */
struct safe : state<safe> {
static constexpr safety_lever lever = safety_lever::safe;
};
struct single : state<single> {
static constexpr safety_lever lever = safety_lever::single;
};
struct automatic : state<automatic> {
static constexpr safety_lever lever = safety_lever::automatic;
};
//@}
51
Действия при переходе
struct update_safety {
template <typename Event, typename FSM,
typename SourceState, typename TargetState>
void
operator()(Event const&, FSM& fsm, SourceState&, TargetState&) const
{
root_machine(fsm).update_safety(TargetState::lever);
}
};
54
Действия при переходе
struct change_magazine {
template <typename Event, typename FSM>
void
operator()(Event const&, FSM& fsm) const
{
root_machine(fsm).reload();
}
};
55
Действия при переходе
struct change_magazine {
template <typename Event, typename FSM>
void
operator()(Event const&, FSM& fsm) const
{
root_machine(fsm).reload();
}
};
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
✓Событие (event)
✓Состояние (state)
✓Действие (action)
✓при входе в состояние (on entry)
✓при выходе из состояния (on exit)
✓при переходе (transition action)
Условие перехода (transition guard)
56
Основные
сущности
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
✓Событие (event)
✓Состояние (state)
✓Действие (action)
✓при входе в состояние (on entry)
✓при выходе из состояния (on exit)
✓при переходе (transition action)
Условие перехода (transition guard)
57
Основные
сущности
58
Условия перехода
struct selector : state_machine<selector> {
/** @name Selector substates */
struct safe;
struct single;
struct automatic;
using initial_state = safe;
// Type aliases to shorten the transition table
using down = events::safety_lever_down;
using up = events::safety_lever_up;
// selector transition table
using transitions = transition_table<
/* State | Event | Next | Action | Guard */
tr< safe , down , automatic , update_safety , none >,
tr< automatic , up , safe , update_safety , not_<firing> >,
tr< automatic , down , single , update_safety , not_<firing> >,
tr< single , up , automatic , update_safety , not_<firing> >
>;
};
59
Условия перехода
struct firing : machine_gun_def::in_state<machine_gun_def::trigger::fire> {};
60
Условия перехода
struct firing : machine_gun_def::in_state<machine_gun_def::trigger::fire> {};
62
Условия перехода
// trigger transition table
using transitions = transition_table<
/* State | Event | Next | Action | Guard */
tr< init , none , ready , none , not_<depleted> >,
tr< init , none , empty , none , depleted >,
tr< empty , reload , ready , change_magazine , none >,
tr< ready , pull , fire , emit_bullet , not_<in_state<selector::safe>> >,
tr< ready , reload , ready , change_magazine , none >,
tr< fire , release , ready , none , none >,
tr< fire , tick , fire , emit_bullet , and_<in_state<selector::automatic>,
want_this_frame,
not_<depleted>> >,
tr< fire , none , empty , none , depleted >
>;
68
Условия перехода
struct depleted {
template <typename FSM, typename State>
bool
operator()(FSM const& fsm, State const&) const
{
return root_machine(fsm).empty();
}
};
struct want_this_frame {
template <typename FSM, typename State>
bool
operator()(FSM const&, State const&, events::tick const& t) const
{
return t.frame % 10 == 0;
}
};
Машина состояний (state machine)
✓Таблица переходов (transition table)
✓Переход (transition)
✓Событие (event)
✓Состояние (state)
✓Действие (action)
✓при входе в состояние (on entry)
✓при выходе из состояния (on exit)
✓при переходе (transition action)
✓Условие перехода (transition guard)
69
Основные
сущности
70
Как это использовать в коде?
namespace guns {
using machine_gun = afsm::state_machine<machine_gun_def>;
} // namespace guns
int
main(int, char*[])
{
guns::machine_gun mg;
mg.process_event(afsm::none{});
mg.process_event(guns::events::safety_lever_down{});
mg.process_event(guns::events::reload{});
mg.process_event(guns::events::trigger_pull{});
while (!mg.empty()) {
mg.process_event(guns::events::tick{});
}
mg.process_event(guns::events::trigger_release{});
return 0;
}
Реализация DSL
https://github.com/zmij/afsm
73
Объявление front machine
namespace guns {
using machine_gun = afsm::state_machine<machine_gun_def>;
} // namespace guns
int
main(int, char*[])
{
guns::machine_gun mg;
mg.process_event(afsm::none{});
mg.process_event(guns::events::safety_lever_down{});
mg.process_event(guns::events::reload{});
mg.process_event(guns::events::trigger_pull{});
while (!mg.empty()) {
mg.process_event(guns::events::tick{});
}
mg.process_event(guns::events::trigger_release{});
return 0;
}
74
Объявление front machine
template <typename T, typename Mutex = none, typename Observer = none,
template <typename> class ObserverWrapper = detail::observer_wrapper>
class state_machine;
75
Transition
template <typename SourceState, typename Event, typename TargetState, typename Action = none,
typename Guard = none>
struct transition {
using source_state_type = SourceState;
using target_state_type = TargetState;
using event_type = Event;
using action_type = Action;
using guard_type = Guard;
using key_type = detail::transition_key<SourceState, Event, Guard>;
struct value_type {
using action_type = transition::action_type;
using target_state_type = transition::target_state_type;
};
};
81
Transition table
template <typename... T>
struct transition_table {
static_assert(
(psst::meta::all_match<traits::is_transition, T...>::type::value),
"Transition table can contain only transition or internal_transition template "
"instantiations");
using transitions = psst::meta::type_tuple<T...>;
using inner_states =
typename psst::meta::unique<typename detail::source_state<T>::type...,
typename detail::target_state<T>::type...>::type;
using handled_events = typename psst::meta::unique<typename T::event_type...>::type;
static constexpr std::size_t inner_state_count = inner_states::size;
static constexpr std::size_t event_count = handled_events::size;
static_assert((psst::meta::all_match<traits::is_state, inner_states>::type::value),
"State types must derive from afsm::def::state");
static_assert(transitions::size == transition_count, "Duplicate transition");
};
86
Transition Source State
template <typename T>
struct source_state;
template <typename SourceState, typename Event, typename TargetState, typename Action,
typename Guard>
struct source_state<transition<SourceState, Event, TargetState, Action, Guard>> {
using type = SourceState;
};
template <typename Event, typename Action, typename Guard>
struct source_state<internal_transition<Event, Action, Guard>> {
using type = void;
};
90
Маленькие хитрости
template <typename StateMachine, typename... Tags>
struct state_machine_def : state_def<StateMachine, Tags…>,
tags::state_machine {
template <typename SourceState, typename Event,
typename TargetState, typename Action = none,
typename Guard = none>
using tr = transition<SourceState, Event, TargetState, Action, Guard>;
template <typename T, typename... TTags>
using state = doesnt_really_matter;
template <typename T, typename... TTags>
using state_machine = doesnt_really_matter;
using none = afsm::none;
template <typename Predicate>
using not_ = psst::meta::not_<Predicate>;
template <typename... Predicates>
using and_ = psst::meta::and_<Predicates...>;
template <typename... Predicates>
using or_ = psst::meta::or_<Predicates...>;
};
92
none
// trigger transition table
using transitions = transition_table<
/* State | Event | Next | Action | Guard */
tr< init , none , ready , none , not_<depleted> >,
tr< init , none , empty , none , depleted >,
tr< empty , reload , ready , change_magazine , none >,
tr< ready , pull , fire , emit_bullet , not_<in_state<selector::safe>> >,
tr< ready , reload , ready , change_magazine , none >,
tr< fire , release , ready , none , none >,
tr< fire , tick , fire , emit_bullet , and_<in_state<selector::automatic>,
want_this_frame,
not_<depleted>> >,
tr< fire , none , empty , none , depleted >
>;
93
none
struct none {};
94
none: action
struct none {};
template <typename FSM, typename SourceState, typename TargetState>
struct action_invocation<none, FSM, SourceState, TargetState> {
template <typename Event>
void
operator()(Event&&, FSM&, SourceState&, TargetState&) const
{}
};
95
none: guard
struct none {};
template <typename FSM, typename State, typename Event>
struct guard_check<FSM, State, Event, none> {
constexpr bool
operator()(FSM const&, State const&, Event const&) const
{
return true;
}
};
96
none: event
struct none {};
void
check_default_transition()
{
auto const& ttable = transition_table<none>(state_indexes{});
ttable[current_state()](*this, none{});
}
97
Обработка обычного действия при переходе
template <typename Event>
actions::event_process_result
process_transition_event(Event&& event)
{
auto const& inv_table = transition_table<Event>(state_indexes{});
return inv_table[current_state()](*this, std::forward<Event>(event));
}
98
Transition table для текущего события
template <typename Event, std::size_t... Indexes>
static transition_table_type<Event> const&
transition_table(psst::meta::indexes_tuple<Indexes...> const&)
{
using event_type = typename std::decay<Event>::type;
using event_transitions =
typename psst::meta::find_if<def::handles_event<event_type>::template type,
transitions_tuple>::type;
static transition_table_type<Event> _table{{
typename detail::transition_action_selector<fsm_type, this_type,
typename psst::meta::find_if<
def::originates_from<
typename inner_states_def::template type<Indexes>
>::template type,
event_transitions
>::type
>::type{}...}};
return _table;
}
99
Transition table для текущего события
template <typename Event, std::size_t... Indexes>
static transition_table_type<Event> const&
transition_table(psst::meta::indexes_tuple<Indexes...> const&)
{
using event_type = typename std::decay<Event>::type;
using event_transitions =
typename psst::meta::find_if<def::handles_event<event_type>::template type,
transitions_tuple>::type;
static transition_table_type<Event> _table{{
typename detail::transition_action_selector<fsm_type, this_type,
typename psst::meta::find_if<
def::originates_from<
typename inner_states_def::template type<Indexes>
>::template type,
event_transitions
>::type
>::type{}...}};
return _table;
}
100
Transition table для текущего события
template <typename Event, std::size_t... Indexes>
static transition_table_type<Event> const&
transition_table(psst::meta::indexes_tuple<Indexes...> const&)
{
using event_type = typename std::decay<Event>::type;
using event_transitions =
typename psst::meta::find_if<def::handles_event<event_type>::template type,
transitions_tuple>::type;
static transition_table_type<Event> _table{{
typename detail::transition_action_selector<fsm_type, this_type,
typename psst::meta::find_if<
def::originates_from<
typename inner_states_def::template type<Indexes>
>::template type,
event_transitions
>::type
>::type{}...}};
return _table;
}
101
meta::find_if
namespace detail {
template <template <typename> class Predicate, std::size_t N, typename... T>
struct find_if_impl;
template <template <typename> class Predicate, std::size_t N, typename T, typename... Y>
struct find_if_impl<Predicate, N, T, Y...> {
using tail = find_if_impl<Predicate, N + 1, Y…>;
using type = std::conditional_t<Predicate<T>::value,
combine_t<T, typename tail::type>,
typename tail::type>;
};
} // namespace detail
template <template <typename> class Predicate, typename... T>
struct find_if : detail::find_if_impl<Predicate, 0, T...> {};
102
meta::find_if
namespace detail {
template <template <typename> class Predicate, std::size_t N, typename... T>
struct find_if_impl;
template <template <typename> class Predicate, std::size_t N, typename T, typename... Y>
struct find_if_impl<Predicate, N, T, Y...> {
using tail = find_if_impl<Predicate, N + 1, Y...>;
using type = std::conditional_t<Predicate<T>::value,
combine_t<T, typename tail::type>,
typename tail::type>;
};
} // namespace detail
template <template <typename> class Predicate, typename... T>
struct find_if : detail::find_if_impl<Predicate, 0, T...> {};
103
meta::find_if
namespace detail {
template <template <typename> class Predicate, std::size_t N, typename... T>
struct find_if_impl;
template <template <typename> class Predicate, std::size_t N, typename T, typename... Y>
struct find_if_impl<Predicate, N, T, Y...> {
using tail = find_if_impl<Predicate, N + 1, Y...>;
using type = std::conditional_t<Predicate<T>::value,
combine_t<T, typename tail::type>,
typename tail::type>;
};
} // namespace detail
template <template <typename> class Predicate, typename... T>
struct find_if : detail::find_if_impl<Predicate, 0, T...> {};
104
meta::find_if
namespace detail {
template <template <typename> class Predicate, std::size_t N, typename... T>
struct find_if_impl;
template <template <typename> class Predicate, std::size_t N, typename T, typename... Y>
struct find_if_impl<Predicate, N, T, Y...> {
using tail = find_if_impl<Predicate, N + 1, Y...>;
using type = std::conditional_t<Predicate<T>::value,
combine_t<T, typename tail::type>,
typename tail::type>;
};
} // namespace detail
template <template <typename> class Predicate, typename... T>
struct find_if : detail::find_if_impl<Predicate, 0, T...> {};
105
meta::find_if
namespace detail {
template <template <typename> class Predicate, std::size_t N, typename... T>
struct find_if_impl;
template <template <typename> class Predicate, std::size_t N, typename T, typename... Y>
struct find_if_impl<Predicate, N, T, Y...> {
using tail = find_if_impl<Predicate, N + 1, Y...>;
using type = std::conditional_t<Predicate<T>::value,
combine_t<T, typename tail::type>,
typename tail::type>;
};
} // namespace detail
template <template <typename> class Predicate, typename... T>
struct find_if : detail::find_if_impl<Predicate, 0, T...> {};
Где можно применить?
• Лексические анализаторы
• Сетевые протоколы
• Симуляторы
• Игры
107
Где применить?
108
Пример
/** @name Transition table for transaction */
using transitions = transition_table<
/* Start Event Next Action */
/*+----------------+---------------------------+-------------------+-----------------------+ */
tr< starting , events::ready_for_query , idle , transaction_started >,
/*+----------------+---------------------------+-------------------+-----------------------+ */
tr< idle , events::commit , exiting , commit_transaction >,
tr< idle , events::rollback , exiting , rollback_transaction >,
tr< idle , error::query_error , exiting , rollback_transaction >,
tr< idle , error::client_error , exiting , rollback_transaction >,
/*+----------------+---------------------------+-------------------+-----------------------+ */
tr< idle , events::execute , simple_query , none >,
tr< simple_query , events::ready_for_query , idle , none >,
tr< simple_query , error::query_error , tran_error , none >,
tr< simple_query , error::client_error , tran_error , none >,
tr< simple_query , error::db_error , tran_error , none >,
/*+----------------+---------------------------+-------------------+-----------------------+ */
tr< idle , events::execute_prepared , extended_query , none >,
tr< extended_query , events::ready_for_query , idle , none >,
tr< extended_query , error::query_error , tran_error , none >,
tr< extended_query , error::client_error , tran_error , none >,
tr< extended_query , error::db_error , tran_error , none >,
/*+----------------+---------------------------+-------------------+-----------------------+ */
tr< tran_error , events::ready_for_query , exiting , rollback_transaction >
>;
Спасибо
Ведущий разработчик
ser-fedorov@yandex-team.ru
@zmij_r
Сергей Федоров
https://github.com/zmij
Bonus Slides
112
and_
template <typename... Predicate>
struct and_;
template <typename Predicate, typename... Rest>
struct and_<Predicate, Rest...> {
template <typename... Args>
bool
operator()(Args&&... args) const
{
return Predicate{}(::std::forward<Args>(args)...)
&& and_<Rest...>{}(::std::forward<Args>(args)...);
}
};
template <typename Predicate>
struct and_<Predicate> {
template <typename... Args>
bool
operator()(Args&&... args) const
{
return Predicate{}(::std::forward<Args>(args)...);
}
};
113
and_ - C++17
template <typename... Predicate>
struct and_ {
template <typename... Args>
bool
operator()(Args&&... args) const
{
return (Predicate{}(std::forward<Args>(args)...) && ...);
}
};

More Related Content

What's hot

Аскетичная разработка браузера
Аскетичная разработка браузераАскетичная разработка браузера
Аскетичная разработка браузераPlatonov Sergey
 
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Platonov Sergey
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыPlatonov Sergey
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Sergey Platonov
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаSergey Platonov
 
Юнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, GoogleЮнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, Googleyaevents
 
Введение в Clojure (Никита Прокопов)
Введение в Clojure (Никита Прокопов)Введение в Clojure (Никита Прокопов)
Введение в Clojure (Никита Прокопов)mainstreamless
 
20090222 parallel programming_lecture01-07
20090222 parallel programming_lecture01-0720090222 parallel programming_lecture01-07
20090222 parallel programming_lecture01-07Computer Science Club
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Dima Dzuba
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияSergey Platonov
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода Pavel Tsukanov
 
Антон Полухин, Немного о Boost
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о BoostSergey Platonov
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловSergey Platonov
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Sergey Platonov
 
TMPA-2013 Tsytelov Trifanov Devexperts
TMPA-2013 Tsytelov Trifanov DevexpertsTMPA-2013 Tsytelov Trifanov Devexperts
TMPA-2013 Tsytelov Trifanov DevexpertsIosif Itkin
 
Жилье комфорт-класса для акторов и хендлеров. Максим Хижинский. CoreHard Spri...
Жилье комфорт-класса для акторов и хендлеров. Максим Хижинский. CoreHard Spri...Жилье комфорт-класса для акторов и хендлеров. Максим Хижинский. CoreHard Spri...
Жилье комфорт-класса для акторов и хендлеров. Максим Хижинский. CoreHard Spri...corehard_by
 

What's hot (19)

Аскетичная разработка браузера
Аскетичная разработка браузераАскетичная разработка браузера
Аскетичная разработка браузера
 
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансы
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
Юнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, GoogleЮнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, Google
 
верификация
верификацияверификация
верификация
 
Введение в Clojure (Никита Прокопов)
Введение в Clojure (Никита Прокопов)Введение в Clojure (Никита Прокопов)
Введение в Clojure (Никита Прокопов)
 
20090222 parallel programming_lecture01-07
20090222 parallel programming_lecture01-0720090222 parallel programming_lecture01-07
20090222 parallel programming_lecture01-07
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6
 
02 if for
02 if for02 if for
02 if for
 
Parallel STL
Parallel STLParallel STL
Parallel STL
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизация
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода
 
Антон Полухин, Немного о Boost
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о Boost
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
 
TMPA-2013 Tsytelov Trifanov Devexperts
TMPA-2013 Tsytelov Trifanov DevexpertsTMPA-2013 Tsytelov Trifanov Devexperts
TMPA-2013 Tsytelov Trifanov Devexperts
 
Жилье комфорт-класса для акторов и хендлеров. Максим Хижинский. CoreHard Spri...
Жилье комфорт-класса для акторов и хендлеров. Максим Хижинский. CoreHard Spri...Жилье комфорт-класса для акторов и хендлеров. Максим Хижинский. CoreHard Spri...
Жилье комфорт-класса для акторов и хендлеров. Максим Хижинский. CoreHard Spri...
 

Similar to Метапрограммирование: строим конечный автомат. Сергей Федоров ➠ CoreHard Autumn 2019

Cтатический анализ кода (на примере DDD-фреймворка)
Cтатический анализ кода (на примере DDD-фреймворка)Cтатический анализ кода (на примере DDD-фреймворка)
Cтатический анализ кода (на примере DDD-фреймворка)ngrebnev
 
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...solit
 
КРИ 2008. Проектирование игр: функциональный подход
КРИ 2008. Проектирование игр: функциональный подходКРИ 2008. Проектирование игр: функциональный подход
КРИ 2008. Проектирование игр: функциональный подходKirill Lebedev
 
Lecture5
Lecture5Lecture5
Lecture5orgil
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castRoman Orlov
 
Уменьшение влияния человеческого фактора при разработке бизнес приложений
Уменьшение влияния человеческого фактора при разработке бизнес приложенийУменьшение влияния человеческого фактора при разработке бизнес приложений
Уменьшение влияния человеческого фактора при разработке бизнес приложенийngrebnev
 
Flink CEP и немного магии...
Flink CEP и немного магии...Flink CEP и немного магии...
Flink CEP и немного магии...Alexander Chermenin
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMTech Talks @NSU
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кодаAndrey Karpov
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Yandex
 
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...Sigma Software
 
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...Alexey Paznikov
 
2012 03 14_parallel_programming_lecture05
2012 03 14_parallel_programming_lecture052012 03 14_parallel_programming_lecture05
2012 03 14_parallel_programming_lecture05Computer Science Club
 
Mera Dev Fest - Swift vs. Obj-C
Mera Dev Fest - Swift vs. Obj-CMera Dev Fest - Swift vs. Obj-C
Mera Dev Fest - Swift vs. Obj-CSergey Pronin
 
основы Java переменные, циклы
основы Java   переменные, циклыосновы Java   переменные, циклы
основы Java переменные, циклыSergey Nemchinsky
 
обработка исключений в Java
обработка исключений в Javaобработка исключений в Java
обработка исключений в Javametaform
 

Similar to Метапрограммирование: строим конечный автомат. Сергей Федоров ➠ CoreHard Autumn 2019 (20)

Cтатический анализ кода (на примере DDD-фреймворка)
Cтатический анализ кода (на примере DDD-фреймворка)Cтатический анализ кода (на примере DDD-фреймворка)
Cтатический анализ кода (на примере DDD-фреймворка)
 
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
 
КРИ 2008. Проектирование игр: функциональный подход
КРИ 2008. Проектирование игр: функциональный подходКРИ 2008. Проектирование игр: функциональный подход
КРИ 2008. Проектирование игр: функциональный подход
 
Lecture5
Lecture5Lecture5
Lecture5
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_cast
 
Уменьшение влияния человеческого фактора при разработке бизнес приложений
Уменьшение влияния человеческого фактора при разработке бизнес приложенийУменьшение влияния человеческого фактора при разработке бизнес приложений
Уменьшение влияния человеческого фактора при разработке бизнес приложений
 
лекция 2
лекция 2лекция 2
лекция 2
 
Flink CEP и немного магии...
Flink CEP и немного магии...Flink CEP и немного магии...
Flink CEP и немного магии...
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVM
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...
 
Odd
OddOdd
Odd
 
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
 
2012 03 14_parallel_programming_lecture05
2012 03 14_parallel_programming_lecture052012 03 14_parallel_programming_lecture05
2012 03 14_parallel_programming_lecture05
 
Mera Dev Fest - Swift vs. Obj-C
Mera Dev Fest - Swift vs. Obj-CMera Dev Fest - Swift vs. Obj-C
Mera Dev Fest - Swift vs. Obj-C
 
основы Java переменные, циклы
основы Java   переменные, циклыосновы Java   переменные, циклы
основы Java переменные, циклы
 
обработка исключений в Java
обработка исключений в Javaобработка исключений в Java
обработка исключений в Java
 
Fiche Révision POO
Fiche Révision POOFiche Révision POO
Fiche Révision POO
 

More from corehard_by

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...corehard_by
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...corehard_by
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотниковcorehard_by
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титовcorehard_by
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...corehard_by
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишковcorehard_by
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...corehard_by
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...corehard_by
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...corehard_by
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...corehard_by
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...corehard_by
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...corehard_by
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филоновcorehard_by
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukićcorehard_by
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakovacorehard_by
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухинcorehard_by
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...corehard_by
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019corehard_by
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019corehard_by
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019corehard_by
 

More from corehard_by (20)

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
 

Метапрограммирование: строим конечный автомат. Сергей Федоров ➠ CoreHard Autumn 2019

  • 1.
  • 2. Метапрограммирование: Строим конечный автомат offline online connect connecting connected connection failed idle transaction begin commit rollback disconnected tran idle simple mode extended mode exec exec prepared
  • 3. Конечный автомат - что это? DSL для конечного автомата Реализация DSL Где можно применить? 5 О чём поговорим
  • 5. Конечный автомат – абстрактный автомат, число внутренних состояний которого конечно. 7https://ru.wikipedia.org/wiki/Конечный_автомат Определение из Википедии
  • 6. M = (V, Q, q0, F, δ) //*[sS]*?*/|([^:]|^)//.*$/gm statement
 : 'if' paren_expr statement
 | 'if' paren_expr statement 'else' statement
 | 'while' paren_expr statement
 | 'do' statement 'while' paren_expr ';'
 | '{' statement* '}'
 | expr ';'
 | ';'
 ; 8 Как выглядит?
  • 7. 9 Простейший КА на примере АК ready fire pull / emit bullet release t ullet release tick / emit bullet
  • 8. 12 Условные переходы Sergei Fedorov | November 10, 2019 ready pull / emit bullet release empty reload [depleted][!depleted] [depleted] fire tick / emit bullet [!depleted]
  • 9. 14 Ортогональные состояния AK47 Sergei Fedorov | November 10, 2019 Trigger Machine gun Safety lock safe auto single down down [!firing] up [!firing] up [!firing] ready pull / emit bullet release empty reload [depleted][!depleted] [depleted] fire tick / emit bullet [auto && !depleted]
  • 10. 15 Табличное представление State Event Next State Action Condition (guard) trigger initial - ready !depleted initial - empty depleted empty reload ready change magazine ready reload fire change magazine ready pull the trigger fire emit bullet !safe fire release the trigger ready fire tick fire emit bullet automatic && !depleted fire - empty depleted selector safe lever down automatic automatic lever up safe !firing automatic lever down single !firing single lever up automatic !firing
  • 11. DSL для конечного автомата
  • 12. Машина состояний (state machine) Таблица переходов (transition table) Переход (transition) Событие (event) Состояние (state) Действие (action) при входе в состояние (on entry) при выходе из состояния (on exit) при переходе (transition action) Условие перехода (transition guard) 17 Основные сущности
  • 13. Машина состояний (state machine) Таблица переходов (transition table) Переход (transition) Событие (event) Состояние (state) Действие (action) при входе в состояние (on entry) при выходе из состояния (on exit) при переходе (transition action) Условие перехода (transition guard) 18 Основные сущности
  • 14. 19 КА с ортогональными состояниями struct machine_gun_def : afsm::def::state_machine<machine_gun_def> { //@{ /** @name Sub-machines */ struct selector; struct trigger; using orthogonal_regions = type_tuple<trigger, selector>; //@} };
  • 15. 20 Табличное представление State Event Next State Action Condition (guard) trigger initial - ready !depleted initial - empty depleted empty reload ready change magazine ready reload fire change magazine ready pull the trigger fire emit bullet !safe fire release the trigger ready fire tick fire emit bullet automatic && !depleted fire - empty depleted selector safe lever down automatic automatic lever up safe !firing automatic lever down single !firing single lever up automatic !firing
  • 16. 21 Табличное представление State Event Next State Action Condition (guard) trigger initial - ready !depleted initial - empty depleted empty reload ready change magazine ready reload fire change magazine ready pull the trigger fire emit bullet !safe fire release the trigger ready fire tick fire emit bullet automatic && !depleted fire - empty depleted selector safe lever down automatic automatic lever up safe !firing automatic lever down single !firing single lever up automatic !firing
  • 17. 22 Машина состояний struct selector : state_machine<selector> { /** @name Selector substates */ struct safe; struct single; struct automatic; using initial_state = safe; // Type aliases to shorten the transition table using down = events::safety_lever_down; using up = events::safety_lever_up; // selector transition table using transitions = transition_table< /* State | Event | Next | Action | Guard */ tr< safe , down , automatic , update_safety , none >, tr< automatic , up , safe , update_safety , not_<firing> >, tr< automatic , down , single , update_safety , not_<firing> >, tr< single , up , automatic , update_safety , not_<firing> > >; };
  • 18. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) Событие (event) Состояние (state) Действие (action) при входе в состояние (on entry) при выходе из состояния (on exit) при переходе (transition action) Условие перехода (transition guard) 33 Основные сущности
  • 19. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) Событие (event) Состояние (state) Действие (action) при входе в состояние (on entry) при выходе из состояния (on exit) при переходе (transition action) Условие перехода (transition guard) 34 Основные сущности
  • 20. 35 Описание событий namespace guns::events { struct trigger_pull {}; struct trigger_release {}; struct reload {}; struct safety_lever_up {}; struct safety_lever_down {}; struct tick { std::uint64_t frame = 0; }; } // namespace guns::events
  • 21. 36 Описание событий namespace guns::events { struct trigger_pull {}; struct trigger_release {}; struct reload {}; struct safety_lever_up {}; struct safety_lever_down {}; struct tick { std::uint64_t frame = 0; }; } // namespace guns::events
  • 22. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) ✓Событие (event) Состояние (state) Действие (action) при входе в состояние (on entry) при выходе из состояния (on exit) при переходе (transition action) Условие перехода (transition guard) 37 Основные сущности
  • 23. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) ✓Событие (event) Состояние (state) Действие (action) при входе в состояние (on entry) при выходе из состояния (on exit) при переходе (transition action) Условие перехода (transition guard) 38 Основные сущности
  • 24. 39 Описание состояний //@{ /** @name Selector substates */ struct safe : state<safe> { static constexpr safety_lever lever = safety_lever::safe; }; struct single : state<single> { static constexpr safety_lever lever = safety_lever::single; }; struct automatic : state<automatic> { static constexpr safety_lever lever = safety_lever::automatic; }; //@}
  • 25. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) ✓Событие (event) ✓Состояние (state) Действие (action) при входе в состояние (on entry) при выходе из состояния (on exit) при переходе (transition action) Условие перехода (transition guard) 41 Основные сущности
  • 26. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) ✓Событие (event) ✓Состояние (state) Действие (action) при входе в состояние (on entry) при выходе из состояния (on exit) при переходе (transition action) Условие перехода (transition guard) 42 Основные сущности
  • 27. 44 Действия при входе/выходе struct empty : state<empty> { template <typename FSM> void on_enter(afsm::none&&, FSM& fsm) { root_machine(fsm).ammo_depleted(); } template <typename FSM> void on_exit(events::reload const&, FSM& fsm) { root_machine(fsm).ammo_replentished(); } };
  • 28. 45 Действия при входе/выходе struct empty : state<empty> { template <typename FSM> void on_enter(afsm::none&&, FSM& fsm) { root_machine(fsm).ammo_depleted(); } template <typename FSM> void on_exit(events::reload const&, FSM& fsm) { root_machine(fsm).ammo_replentished(); } };
  • 29. 46 Действия при входе/выходе struct empty : state<empty> { template <typename FSM> void on_enter(afsm::none&&, FSM& fsm) { root_machine(fsm).ammo_depleted(); } template <typename FSM> void on_exit(events::reload const&, FSM& fsm) { root_machine(fsm).ammo_replentished(); } };
  • 30. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) ✓Событие (event) ✓Состояние (state) Действие (action) ✓при входе в состояние (on entry) ✓при выходе из состояния (on exit) при переходе (transition action) Условие перехода (transition guard) 47 Основные сущности
  • 31. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) ✓Событие (event) ✓Состояние (state) Действие (action) ✓при входе в состояние (on entry) ✓при выходе из состояния (on exit) при переходе (transition action) Условие перехода (transition guard) 48 Основные сущности
  • 32. 49 Действия при переходе struct selector : state_machine<selector> { /** @name Selector substates */ struct safe; struct single; struct automatic; using initial_state = safe; // Type aliases to shorten the transition table using down = events::safety_lever_down; using up = events::safety_lever_up; // selector transition table using transitions = transition_table< /* State | Event | Next | Action | Guard */ tr< safe , down , automatic , update_safety , none >, tr< automatic , up , safe , update_safety , not_<firing> >, tr< automatic , down , single , update_safety , not_<firing> >, tr< single , up , automatic , update_safety , not_<firing> > >; };
  • 33. 50 Действия при переходе //@{ /** @name Selector substates */ struct safe : state<safe> { static constexpr safety_lever lever = safety_lever::safe; }; struct single : state<single> { static constexpr safety_lever lever = safety_lever::single; }; struct automatic : state<automatic> { static constexpr safety_lever lever = safety_lever::automatic; }; //@}
  • 34. 51 Действия при переходе struct update_safety { template <typename Event, typename FSM, typename SourceState, typename TargetState> void operator()(Event const&, FSM& fsm, SourceState&, TargetState&) const { root_machine(fsm).update_safety(TargetState::lever); } };
  • 35. 54 Действия при переходе struct change_magazine { template <typename Event, typename FSM> void operator()(Event const&, FSM& fsm) const { root_machine(fsm).reload(); } };
  • 36. 55 Действия при переходе struct change_magazine { template <typename Event, typename FSM> void operator()(Event const&, FSM& fsm) const { root_machine(fsm).reload(); } };
  • 37. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) ✓Событие (event) ✓Состояние (state) ✓Действие (action) ✓при входе в состояние (on entry) ✓при выходе из состояния (on exit) ✓при переходе (transition action) Условие перехода (transition guard) 56 Основные сущности
  • 38. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) ✓Событие (event) ✓Состояние (state) ✓Действие (action) ✓при входе в состояние (on entry) ✓при выходе из состояния (on exit) ✓при переходе (transition action) Условие перехода (transition guard) 57 Основные сущности
  • 39. 58 Условия перехода struct selector : state_machine<selector> { /** @name Selector substates */ struct safe; struct single; struct automatic; using initial_state = safe; // Type aliases to shorten the transition table using down = events::safety_lever_down; using up = events::safety_lever_up; // selector transition table using transitions = transition_table< /* State | Event | Next | Action | Guard */ tr< safe , down , automatic , update_safety , none >, tr< automatic , up , safe , update_safety , not_<firing> >, tr< automatic , down , single , update_safety , not_<firing> >, tr< single , up , automatic , update_safety , not_<firing> > >; };
  • 40. 59 Условия перехода struct firing : machine_gun_def::in_state<machine_gun_def::trigger::fire> {};
  • 41. 60 Условия перехода struct firing : machine_gun_def::in_state<machine_gun_def::trigger::fire> {};
  • 42. 62 Условия перехода // trigger transition table using transitions = transition_table< /* State | Event | Next | Action | Guard */ tr< init , none , ready , none , not_<depleted> >, tr< init , none , empty , none , depleted >, tr< empty , reload , ready , change_magazine , none >, tr< ready , pull , fire , emit_bullet , not_<in_state<selector::safe>> >, tr< ready , reload , ready , change_magazine , none >, tr< fire , release , ready , none , none >, tr< fire , tick , fire , emit_bullet , and_<in_state<selector::automatic>, want_this_frame, not_<depleted>> >, tr< fire , none , empty , none , depleted > >;
  • 43. 68 Условия перехода struct depleted { template <typename FSM, typename State> bool operator()(FSM const& fsm, State const&) const { return root_machine(fsm).empty(); } }; struct want_this_frame { template <typename FSM, typename State> bool operator()(FSM const&, State const&, events::tick const& t) const { return t.frame % 10 == 0; } };
  • 44. Машина состояний (state machine) ✓Таблица переходов (transition table) ✓Переход (transition) ✓Событие (event) ✓Состояние (state) ✓Действие (action) ✓при входе в состояние (on entry) ✓при выходе из состояния (on exit) ✓при переходе (transition action) ✓Условие перехода (transition guard) 69 Основные сущности
  • 45. 70 Как это использовать в коде? namespace guns { using machine_gun = afsm::state_machine<machine_gun_def>; } // namespace guns int main(int, char*[]) { guns::machine_gun mg; mg.process_event(afsm::none{}); mg.process_event(guns::events::safety_lever_down{}); mg.process_event(guns::events::reload{}); mg.process_event(guns::events::trigger_pull{}); while (!mg.empty()) { mg.process_event(guns::events::tick{}); } mg.process_event(guns::events::trigger_release{}); return 0; }
  • 47. 73 Объявление front machine namespace guns { using machine_gun = afsm::state_machine<machine_gun_def>; } // namespace guns int main(int, char*[]) { guns::machine_gun mg; mg.process_event(afsm::none{}); mg.process_event(guns::events::safety_lever_down{}); mg.process_event(guns::events::reload{}); mg.process_event(guns::events::trigger_pull{}); while (!mg.empty()) { mg.process_event(guns::events::tick{}); } mg.process_event(guns::events::trigger_release{}); return 0; }
  • 48. 74 Объявление front machine template <typename T, typename Mutex = none, typename Observer = none, template <typename> class ObserverWrapper = detail::observer_wrapper> class state_machine;
  • 49. 75 Transition template <typename SourceState, typename Event, typename TargetState, typename Action = none, typename Guard = none> struct transition { using source_state_type = SourceState; using target_state_type = TargetState; using event_type = Event; using action_type = Action; using guard_type = Guard; using key_type = detail::transition_key<SourceState, Event, Guard>; struct value_type { using action_type = transition::action_type; using target_state_type = transition::target_state_type; }; };
  • 50. 81 Transition table template <typename... T> struct transition_table { static_assert( (psst::meta::all_match<traits::is_transition, T...>::type::value), "Transition table can contain only transition or internal_transition template " "instantiations"); using transitions = psst::meta::type_tuple<T...>; using inner_states = typename psst::meta::unique<typename detail::source_state<T>::type..., typename detail::target_state<T>::type...>::type; using handled_events = typename psst::meta::unique<typename T::event_type...>::type; static constexpr std::size_t inner_state_count = inner_states::size; static constexpr std::size_t event_count = handled_events::size; static_assert((psst::meta::all_match<traits::is_state, inner_states>::type::value), "State types must derive from afsm::def::state"); static_assert(transitions::size == transition_count, "Duplicate transition"); };
  • 51. 86 Transition Source State template <typename T> struct source_state; template <typename SourceState, typename Event, typename TargetState, typename Action, typename Guard> struct source_state<transition<SourceState, Event, TargetState, Action, Guard>> { using type = SourceState; }; template <typename Event, typename Action, typename Guard> struct source_state<internal_transition<Event, Action, Guard>> { using type = void; };
  • 52. 90 Маленькие хитрости template <typename StateMachine, typename... Tags> struct state_machine_def : state_def<StateMachine, Tags…>, tags::state_machine { template <typename SourceState, typename Event, typename TargetState, typename Action = none, typename Guard = none> using tr = transition<SourceState, Event, TargetState, Action, Guard>; template <typename T, typename... TTags> using state = doesnt_really_matter; template <typename T, typename... TTags> using state_machine = doesnt_really_matter; using none = afsm::none; template <typename Predicate> using not_ = psst::meta::not_<Predicate>; template <typename... Predicates> using and_ = psst::meta::and_<Predicates...>; template <typename... Predicates> using or_ = psst::meta::or_<Predicates...>; };
  • 53. 92 none // trigger transition table using transitions = transition_table< /* State | Event | Next | Action | Guard */ tr< init , none , ready , none , not_<depleted> >, tr< init , none , empty , none , depleted >, tr< empty , reload , ready , change_magazine , none >, tr< ready , pull , fire , emit_bullet , not_<in_state<selector::safe>> >, tr< ready , reload , ready , change_magazine , none >, tr< fire , release , ready , none , none >, tr< fire , tick , fire , emit_bullet , and_<in_state<selector::automatic>, want_this_frame, not_<depleted>> >, tr< fire , none , empty , none , depleted > >;
  • 55. 94 none: action struct none {}; template <typename FSM, typename SourceState, typename TargetState> struct action_invocation<none, FSM, SourceState, TargetState> { template <typename Event> void operator()(Event&&, FSM&, SourceState&, TargetState&) const {} };
  • 56. 95 none: guard struct none {}; template <typename FSM, typename State, typename Event> struct guard_check<FSM, State, Event, none> { constexpr bool operator()(FSM const&, State const&, Event const&) const { return true; } };
  • 57. 96 none: event struct none {}; void check_default_transition() { auto const& ttable = transition_table<none>(state_indexes{}); ttable[current_state()](*this, none{}); }
  • 58. 97 Обработка обычного действия при переходе template <typename Event> actions::event_process_result process_transition_event(Event&& event) { auto const& inv_table = transition_table<Event>(state_indexes{}); return inv_table[current_state()](*this, std::forward<Event>(event)); }
  • 59. 98 Transition table для текущего события template <typename Event, std::size_t... Indexes> static transition_table_type<Event> const& transition_table(psst::meta::indexes_tuple<Indexes...> const&) { using event_type = typename std::decay<Event>::type; using event_transitions = typename psst::meta::find_if<def::handles_event<event_type>::template type, transitions_tuple>::type; static transition_table_type<Event> _table{{ typename detail::transition_action_selector<fsm_type, this_type, typename psst::meta::find_if< def::originates_from< typename inner_states_def::template type<Indexes> >::template type, event_transitions >::type >::type{}...}}; return _table; }
  • 60. 99 Transition table для текущего события template <typename Event, std::size_t... Indexes> static transition_table_type<Event> const& transition_table(psst::meta::indexes_tuple<Indexes...> const&) { using event_type = typename std::decay<Event>::type; using event_transitions = typename psst::meta::find_if<def::handles_event<event_type>::template type, transitions_tuple>::type; static transition_table_type<Event> _table{{ typename detail::transition_action_selector<fsm_type, this_type, typename psst::meta::find_if< def::originates_from< typename inner_states_def::template type<Indexes> >::template type, event_transitions >::type >::type{}...}}; return _table; }
  • 61. 100 Transition table для текущего события template <typename Event, std::size_t... Indexes> static transition_table_type<Event> const& transition_table(psst::meta::indexes_tuple<Indexes...> const&) { using event_type = typename std::decay<Event>::type; using event_transitions = typename psst::meta::find_if<def::handles_event<event_type>::template type, transitions_tuple>::type; static transition_table_type<Event> _table{{ typename detail::transition_action_selector<fsm_type, this_type, typename psst::meta::find_if< def::originates_from< typename inner_states_def::template type<Indexes> >::template type, event_transitions >::type >::type{}...}}; return _table; }
  • 62. 101 meta::find_if namespace detail { template <template <typename> class Predicate, std::size_t N, typename... T> struct find_if_impl; template <template <typename> class Predicate, std::size_t N, typename T, typename... Y> struct find_if_impl<Predicate, N, T, Y...> { using tail = find_if_impl<Predicate, N + 1, Y…>; using type = std::conditional_t<Predicate<T>::value, combine_t<T, typename tail::type>, typename tail::type>; }; } // namespace detail template <template <typename> class Predicate, typename... T> struct find_if : detail::find_if_impl<Predicate, 0, T...> {};
  • 63. 102 meta::find_if namespace detail { template <template <typename> class Predicate, std::size_t N, typename... T> struct find_if_impl; template <template <typename> class Predicate, std::size_t N, typename T, typename... Y> struct find_if_impl<Predicate, N, T, Y...> { using tail = find_if_impl<Predicate, N + 1, Y...>; using type = std::conditional_t<Predicate<T>::value, combine_t<T, typename tail::type>, typename tail::type>; }; } // namespace detail template <template <typename> class Predicate, typename... T> struct find_if : detail::find_if_impl<Predicate, 0, T...> {};
  • 64. 103 meta::find_if namespace detail { template <template <typename> class Predicate, std::size_t N, typename... T> struct find_if_impl; template <template <typename> class Predicate, std::size_t N, typename T, typename... Y> struct find_if_impl<Predicate, N, T, Y...> { using tail = find_if_impl<Predicate, N + 1, Y...>; using type = std::conditional_t<Predicate<T>::value, combine_t<T, typename tail::type>, typename tail::type>; }; } // namespace detail template <template <typename> class Predicate, typename... T> struct find_if : detail::find_if_impl<Predicate, 0, T...> {};
  • 65. 104 meta::find_if namespace detail { template <template <typename> class Predicate, std::size_t N, typename... T> struct find_if_impl; template <template <typename> class Predicate, std::size_t N, typename T, typename... Y> struct find_if_impl<Predicate, N, T, Y...> { using tail = find_if_impl<Predicate, N + 1, Y...>; using type = std::conditional_t<Predicate<T>::value, combine_t<T, typename tail::type>, typename tail::type>; }; } // namespace detail template <template <typename> class Predicate, typename... T> struct find_if : detail::find_if_impl<Predicate, 0, T...> {};
  • 66. 105 meta::find_if namespace detail { template <template <typename> class Predicate, std::size_t N, typename... T> struct find_if_impl; template <template <typename> class Predicate, std::size_t N, typename T, typename... Y> struct find_if_impl<Predicate, N, T, Y...> { using tail = find_if_impl<Predicate, N + 1, Y...>; using type = std::conditional_t<Predicate<T>::value, combine_t<T, typename tail::type>, typename tail::type>; }; } // namespace detail template <template <typename> class Predicate, typename... T> struct find_if : detail::find_if_impl<Predicate, 0, T...> {};
  • 68. • Лексические анализаторы • Сетевые протоколы • Симуляторы • Игры 107 Где применить?
  • 69. 108 Пример /** @name Transition table for transaction */ using transitions = transition_table< /* Start Event Next Action */ /*+----------------+---------------------------+-------------------+-----------------------+ */ tr< starting , events::ready_for_query , idle , transaction_started >, /*+----------------+---------------------------+-------------------+-----------------------+ */ tr< idle , events::commit , exiting , commit_transaction >, tr< idle , events::rollback , exiting , rollback_transaction >, tr< idle , error::query_error , exiting , rollback_transaction >, tr< idle , error::client_error , exiting , rollback_transaction >, /*+----------------+---------------------------+-------------------+-----------------------+ */ tr< idle , events::execute , simple_query , none >, tr< simple_query , events::ready_for_query , idle , none >, tr< simple_query , error::query_error , tran_error , none >, tr< simple_query , error::client_error , tran_error , none >, tr< simple_query , error::db_error , tran_error , none >, /*+----------------+---------------------------+-------------------+-----------------------+ */ tr< idle , events::execute_prepared , extended_query , none >, tr< extended_query , events::ready_for_query , idle , none >, tr< extended_query , error::query_error , tran_error , none >, tr< extended_query , error::client_error , tran_error , none >, tr< extended_query , error::db_error , tran_error , none >, /*+----------------+---------------------------+-------------------+-----------------------+ */ tr< tran_error , events::ready_for_query , exiting , rollback_transaction > >;
  • 73. 112 and_ template <typename... Predicate> struct and_; template <typename Predicate, typename... Rest> struct and_<Predicate, Rest...> { template <typename... Args> bool operator()(Args&&... args) const { return Predicate{}(::std::forward<Args>(args)...) && and_<Rest...>{}(::std::forward<Args>(args)...); } }; template <typename Predicate> struct and_<Predicate> { template <typename... Args> bool operator()(Args&&... args) const { return Predicate{}(::std::forward<Args>(args)...); } };
  • 74. 113 and_ - C++17 template <typename... Predicate> struct and_ { template <typename... Args> bool operator()(Args&&... args) const { return (Predicate{}(std::forward<Args>(args)...) && ...); } };