sml.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2016-2019 Kris Jusiak (kris at jusiak dot net)
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #ifndef BOOST_SML_HPP
8 #define BOOST_SML_HPP
9 #if defined(_MSC_VER) && !defined(__clang__)
10 #define COMPILING_WITH_MSVC
11 #endif
12 #if (__cplusplus < 201305L && _MSC_VER < 1900)
13 #error "[Boost].SML requires C++14 support (Clang-3.4+, GCC-5.1+, MSVC-2015+)"
14 #else
15 #define BOOST_SML_VERSION 1'1'0
16 #define BOOST_SML_NAMESPACE_BEGIN \
17  namespace boost { \
18  namespace sml { \
19  inline namespace v1_1_0 {
20 #define BOOST_SML_NAMESPACE_END \
21  } \
22  } \
23  }
24 #if defined(__clang__)
25 #define __BOOST_SML_UNUSED __attribute__((unused))
26 #define __BOOST_SML_VT_INIT \
27  {}
28 #define __BOOST_SML_ZERO_SIZE_ARRAY(...) __VA_ARGS__ _[0]
29 #define __BOOST_SML_ZERO_SIZE_ARRAY_CREATE(...)
30 #define __BOOST_SML_TEMPLATE_KEYWORD template
31 #pragma clang diagnostic push
32 #pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
33 #pragma clang diagnostic ignored "-Wzero-length-array"
34 #elif defined(__GNUC__)
35 #if !defined(__has_builtin)
36 #define __BOOST_SML_DEFINED_HAS_BUILTIN
37 #define __has_builtin(...) 0
38 #endif
39 #define __BOOST_SML_UNUSED __attribute__((unused))
40 #define __BOOST_SML_VT_INIT \
41  {}
42 #define __BOOST_SML_ZERO_SIZE_ARRAY(...) __VA_ARGS__ _[0]
43 #define __BOOST_SML_ZERO_SIZE_ARRAY_CREATE(...) __VA_ARGS__ ? __VA_ARGS__ : 1
44 #define __BOOST_SML_TEMPLATE_KEYWORD template
45 #pragma GCC diagnostic push
46 #pragma GCC diagnostic ignored "-Wpedantic"
47 #elif defined(COMPILING_WITH_MSVC)
48 #define __BOOST_SML_DEFINED_HAS_BUILTIN
49 #define __has_builtin(...) __has_builtin##__VA_ARGS__
50 #define __has_builtin__make_integer_seq(...) 1
51 #define __BOOST_SML_UNUSED
52 #define __BOOST_SML_VT_INIT
53 #define __BOOST_SML_ZERO_SIZE_ARRAY(...)
54 #define __BOOST_SML_ZERO_SIZE_ARRAY_CREATE(...) __VA_ARGS__ ? __VA_ARGS__ : 1
55 #if (defined(COMPILING_WITH_MSVC) && _MSC_VER >= 1910) // MSVC 2017
56 #define __BOOST_SML_TEMPLATE_KEYWORD template
57 #else
58 #define __BOOST_SML_TEMPLATE_KEYWORD
59 #endif
60 #pragma warning(disable : 4503)
61 #pragma warning(disable : 4200)
62 #endif
63 BOOST_SML_NAMESPACE_BEGIN
64 #define __BOOST_SML_REQUIRES(...) typename aux::enable_if<__VA_ARGS__, int>::type = 0
65 namespace aux {
66 using byte = unsigned char;
67 struct none_type {};
68 template <class...>
69 struct type {};
70 template <class T, T>
71 struct non_type {};
72 template <class, class>
73 struct pair {};
74 template <class...>
75 struct type_list {
76  using type = type_list;
77 };
78 template <bool...>
79 struct bool_list {
80  using type = bool_list;
81 };
82 template <class... Ts>
83 struct inherit : Ts... {
84  using type = inherit;
85 };
86 template <class T>
87 struct identity {
88  using type = T;
89 };
90 template <class T>
91 T &&declval();
92 template <class T, T V>
93 struct integral_constant {
94  using type = integral_constant;
95  static constexpr T value = V;
96 };
97 using true_type = integral_constant<bool, true>;
98 using false_type = integral_constant<bool, false>;
99 template <class... Ts>
100 using void_t = void;
101 template <class...>
102 struct always : true_type {};
103 template <class...>
104 struct never : false_type {};
105 template <bool B, class T, class F>
106 struct conditional {
107  using type = T;
108 };
109 template <class T, class F>
110 struct conditional<false, T, F> {
111  using type = F;
112 };
113 template <bool B, class T, class F>
114 using conditional_t = typename conditional<B, T, F>::type;
115 template <bool B, class T = void>
116 struct enable_if {};
117 template <class T>
118 struct enable_if<true, T> {
119  using type = T;
120 };
121 template <bool B, class T = void>
122 using enable_if_t = typename enable_if<B, T>::type;
123 template <class, class>
124 struct is_same : false_type {};
125 template <class T>
126 struct is_same<T, T> : true_type {};
127 template <class T, class U>
128 #if defined(COMPILING_WITH_MSVC)
129 struct is_base_of : integral_constant<bool, __is_base_of(T, U)> {
130 };
131 #else
132 using is_base_of = integral_constant<bool, __is_base_of(T, U)>;
133 #endif
134 template <class T, class... TArgs>
135 decltype(T(declval<TArgs>()...), true_type{}) test_is_constructible(int);
136 template <class, class...>
137 false_type test_is_constructible(...);
138 template <class T, class... TArgs>
139 #if defined(COMPILING_WITH_MSVC)
140 struct is_constructible : decltype(test_is_constructible<T, TArgs...>(0)) {
141 };
142 #else
143 using is_constructible = decltype(test_is_constructible<T, TArgs...>(0));
144 #endif
145 template <class T, class U>
146 struct is_empty_base : T {
147  U _;
148 };
149 template <class T>
150 struct is_empty : aux::integral_constant<bool, sizeof(is_empty_base<T, none_type>) == sizeof(none_type)> {};
151 template <class>
152 struct function_traits;
153 template <class R, class... TArgs>
154 struct function_traits<R (*)(TArgs...)> {
155  using args = type_list<TArgs...>;
156 };
157 template <class R, class... TArgs>
158 struct function_traits<R(TArgs...)> {
159  using args = type_list<TArgs...>;
160 };
161 template <class R, class T, class... TArgs>
162 struct function_traits<R (T::*)(TArgs...)> {
163  using args = type_list<TArgs...>;
164 };
165 template <class R, class T, class... TArgs>
166 struct function_traits<R (T::*)(TArgs...) const> {
167  using args = type_list<TArgs...>;
168 };
169 #if __cplusplus > 201402L && __cpp_noexcept_function_type >= 201510
170 template <class R, class... TArgs>
171 struct function_traits<R (*)(TArgs...) noexcept> {
172  using args = type_list<TArgs...>;
173 };
174 template <class R, class... TArgs>
175 struct function_traits<R(TArgs...) noexcept> {
176  using args = type_list<TArgs...>;
177 };
178 template <class R, class T, class... TArgs>
179 struct function_traits<R (T::*)(TArgs...) noexcept> {
180  using args = type_list<TArgs...>;
181 };
182 template <class R, class T, class... TArgs>
183 struct function_traits<R (T::*)(TArgs...) const noexcept> {
184  using args = type_list<TArgs...>;
185 };
186 #endif
187 template <class T>
188 using function_traits_t = typename function_traits<T>::args;
189 template <class T>
190 struct remove_const {
191  using type = T;
192 };
193 template <class T>
194 struct remove_const<const T> {
195  using type = T;
196 };
197 template <class T>
198 using remove_const_t = typename remove_const<T>::type;
199 template <class T>
200 struct remove_reference {
201  using type = T;
202 };
203 template <class T>
204 struct remove_reference<T &> {
205  using type = T;
206 };
207 template <class T>
208 struct remove_reference<T &&> {
209  using type = T;
210 };
211 template <class T>
212 using remove_reference_t = typename remove_reference<T>::type;
213 }
214 namespace aux {
215 using swallow = int[];
216 template <int...>
217 struct index_sequence {
218  using type = index_sequence;
219 };
220 #if __has_builtin(__make_integer_seq)
221 template <class T, T...>
222 struct integer_sequence;
223 template <int... Ns>
224 struct integer_sequence<int, Ns...> {
225  using type = index_sequence<Ns...>;
226 };
227 template <int N>
228 struct make_index_sequence_impl {
229  using type = typename __make_integer_seq<integer_sequence, int, N>::type;
230 };
231 #else
232 template <class, class>
233 struct concat;
234 template <int... I1, int... I2>
235 struct concat<index_sequence<I1...>, index_sequence<I2...>> : index_sequence<I1..., (sizeof...(I1) + I2)...> {};
236 template <int N>
237 struct make_index_sequence_impl
238  : concat<typename make_index_sequence_impl<N / 2>::type, typename make_index_sequence_impl<N - N / 2>::type>::type {};
239 template <>
240 struct make_index_sequence_impl<0> : index_sequence<> {};
241 template <>
242 struct make_index_sequence_impl<1> : index_sequence<0> {};
243 #endif
244 template <int N>
245 using make_index_sequence = typename make_index_sequence_impl<N>::type;
246 template <class...>
247 struct join {
248  using type = type_list<>;
249 };
250 template <class T>
251 struct join<T> {
252  using type = T;
253 };
254 template <class... Ts>
255 struct join<type_list<Ts...>> : type_list<Ts...> {};
256 template <class... T1s, class... T2s>
257 struct join<type_list<T1s...>, type_list<T2s...>> : type_list<T1s..., T2s...> {};
258 template <class... T1s, class... T2s, class... T3s>
259 struct join<type_list<T1s...>, type_list<T2s...>, type_list<T3s...>> : type_list<T1s..., T2s..., T3s...> {};
260 template <class... T1s, class... T2s, class... Ts>
261 struct join<type_list<T1s...>, type_list<T2s...>, Ts...> : join<type_list<T1s..., T2s...>, Ts...> {};
262 template <class... Ts, class... T1s, class... T2s, class... T3s, class... T4s, class... T5s, class... T6s, class... T7s,
263  class... T8s, class... T9s, class... T10s, class... T11s, class... T12s, class... T13s, class... T14s, class... T15s,
264  class... T16s, class... Us>
265 struct join<type_list<Ts...>, type_list<T1s...>, type_list<T2s...>, type_list<T3s...>, type_list<T4s...>, type_list<T5s...>,
266  type_list<T6s...>, type_list<T7s...>, type_list<T8s...>, type_list<T9s...>, type_list<T10s...>, type_list<T11s...>,
267  type_list<T12s...>, type_list<T13s...>, type_list<T14s...>, type_list<T15s...>, type_list<T16s...>, Us...>
268  : join<type_list<Ts..., T1s..., T2s..., T3s..., T4s..., T5s..., T6s..., T7s..., T8s..., T9s..., T10s..., T11s..., T12s...,
269  T13s..., T14s..., T15s..., T16s...>,
270  Us...> {};
271 template <class... TArgs>
272 using join_t = typename join<TArgs...>::type;
273 template <class, class...>
274 struct unique_impl;
275 template <class T1, class T2, class... Rs, class... Ts>
276 struct unique_impl<type<T1, Rs...>, T2, Ts...>
277  : conditional_t<is_base_of<type<T2>, T1>::value, unique_impl<type<inherit<T1>, Rs...>, Ts...>,
278  unique_impl<type<inherit<T1, type<T2>>, Rs..., T2>, Ts...>> {};
279 template <class T1, class... Rs>
280 struct unique_impl<type<T1, Rs...>> : type_list<Rs...> {};
281 template <class... Ts>
282 struct unique : unique_impl<type<none_type>, Ts...> {};
283 template <class T>
284 struct unique<T> : type_list<T> {};
285 template <class... Ts>
286 using unique_t = typename unique<Ts...>::type;
287 template <class, class...>
288 struct is_unique;
289 template <class T>
290 struct is_unique<T> : true_type {};
291 template <class T1, class T2, class... Ts>
292 struct is_unique<T1, T2, Ts...>
293  : conditional_t<is_base_of<type<T2>, T1>::value, false_type, is_unique<inherit<T1, type<T2>>, Ts...>> {};
294 template <class... Ts>
295 using is_unique_t = is_unique<none_type, Ts...>;
296 template <template <class...> class, class>
297 struct apply;
298 template <template <class...> class T, template <class...> class U, class... Ts>
299 struct apply<T, U<Ts...>> {
300  using type = T<Ts...>;
301 };
302 template <template <class...> class T, class D>
303 using apply_t = typename apply<T, D>::type;
304 template <int, class T>
305 struct tuple_type {
306  explicit tuple_type(const T &object) : value(object) {}
307  T value;
308 };
309 template <class, class...>
310 struct tuple_impl;
311 template <int... Ns, class... Ts>
312 struct tuple_impl<index_sequence<Ns...>, Ts...> : tuple_type<Ns, Ts>... {
313  explicit tuple_impl(Ts... ts) : tuple_type<Ns, Ts>(ts)... {}
314 };
315 template <>
316 struct tuple_impl<index_sequence<0>> {
317  __BOOST_SML_ZERO_SIZE_ARRAY(byte);
318 };
319 template <class... Ts>
320 using tuple = tuple_impl<make_index_sequence<sizeof...(Ts)>, Ts...>;
321 template <int N, class T>
322 T &get_by_id(tuple_type<N, T> *object) {
323  return static_cast<tuple_type<N, T> &>(*object).value;
324 }
325 struct init {};
326 struct pool_type_base {
327  __BOOST_SML_ZERO_SIZE_ARRAY(byte);
328 };
329 template <class T>
330 struct pool_type : pool_type_base {
331  explicit pool_type(T object) : value{object} {}
332  template <class TObject>
333  pool_type(init i, TObject object) : value{i, object} {}
334  T value;
335 };
336 template <class T>
337 struct missing_ctor_parameter {
338  static constexpr auto value = false;
339  auto operator()() const { return T{}(); }
340  template <class U, __BOOST_SML_REQUIRES(!aux::is_base_of<pool_type_base, U>::value && aux::is_constructible<U>::value)>
341  operator U() {
342  return {};
343  }
344 #if !defined(COMPILING_WITH_MSVC)
345  template <class TMissing, __BOOST_SML_REQUIRES(!aux::is_base_of<pool_type_base, TMissing>::value)>
346  operator TMissing &() const {
347  static_assert(missing_ctor_parameter<TMissing>::value,
348  "State Machine is missing a constructor parameter! Check out the `missing_ctor_parameter` error to see the "
349  "missing type.");
350  }
351 #endif
352 };
353 template <class T>
354 missing_ctor_parameter<T> try_get(...) {
355  return {};
356 }
357 template <class T>
358 T try_get(const pool_type<T> *object) {
359  return object->value;
360 }
361 template <class T>
362 const T &try_get(const pool_type<const T &> *object) {
363  return object->value;
364 }
365 template <class T>
366 T &try_get(const pool_type<T &> *object) {
367  return object->value;
368 }
369 template <class T, class TPool>
370 T &get(TPool &p) {
371  return static_cast<pool_type<T> &>(p).value;
372 }
373 template <class T, class TPool>
374 const T &cget(const TPool &p) {
375  return static_cast<const pool_type<T> &>(p).value;
376 }
377 template <class... Ts>
378 struct pool : pool_type<Ts>... {
379  using boost_di_inject__ = type_list<Ts...>;
380  pool() = default;
381  explicit pool(Ts... ts) : pool_type<Ts>(ts)... {}
382  template <class... TArgs>
383  pool(init, const pool<TArgs...> &p) : pool_type<Ts>(try_get<aux::remove_const_t<aux::remove_reference_t<Ts>>>(&p))... {}
384  template <class... TArgs>
385  pool(const pool<TArgs...> &p) : pool_type<Ts>(init{}, p)... {}
386 };
387 template <>
388 struct pool<> {
389  using boost_di_inject__ = type_list<>;
390  pool() = default;
391  template <class... Ts>
392  explicit pool(Ts &&...) {}
393  __BOOST_SML_ZERO_SIZE_ARRAY(byte);
394 };
395 template <int, class>
396 struct type_id_type {};
397 template <class, class...>
398 struct type_id_impl;
399 template <int... Ns, class... Ts>
400 struct type_id_impl<index_sequence<Ns...>, Ts...> : type_id_type<Ns, Ts>... {};
401 template <class... Ts>
402 struct type_id : type_id_impl<make_index_sequence<sizeof...(Ts)>, Ts...> {};
403 template <class R, class T, int N>
404 constexpr R get_id(type_id_type<N, T> *) {
405  return static_cast<R>(N);
406 }
407 template <template <class...> class, class T>
408 struct is : false_type {};
409 template <template <class...> class T, class... Ts>
410 struct is<T, T<Ts...>> : true_type {};
411 template <class>
412 struct size;
413 template <template <class...> class T, class... Ts>
414 struct size<T<Ts...>> {
415  static constexpr auto value = sizeof...(Ts);
416 };
417 #if defined(COMPILING_WITH_MSVC)
418 constexpr int max_impl() { return 0; }
419 constexpr int max_impl(int r) { return r; }
420 constexpr int max_impl(int r, int i) { return r > i ? r : i; }
421 constexpr int max_impl(int r, int i, int ints...) { return i > r ? max_impl(i, ints) : max_impl(r, ints); }
422 template <int... Ts>
423 constexpr int max() {
424  return max_impl(Ts...);
425 }
426 #else
427 template <int... Ts>
428 constexpr int max() {
429  int max = 0;
430  (void)swallow{0, (Ts > max ? max = Ts : max)...};
431  return max;
432 }
433 #endif
434 template <class TExpr, class = void>
435 struct zero_wrapper : TExpr {
436  using type = TExpr;
437  explicit zero_wrapper(const TExpr &expr) : TExpr(expr) {}
438  const TExpr &get() const { return *this; }
439 };
440 template <class, class>
441 struct zero_wrapper_impl;
442 template <class TExpr, class... TArgs>
443 struct zero_wrapper_impl<TExpr, type_list<TArgs...>> {
444  auto operator()(TArgs... args) const { return reinterpret_cast<const TExpr &>(*this)(args...); }
445  __BOOST_SML_ZERO_SIZE_ARRAY(byte);
446 };
447 template <class TExpr>
448 struct zero_wrapper<TExpr, void_t<decltype(+declval<TExpr>())>>
449  : zero_wrapper_impl<TExpr, function_traits_t<decltype(&TExpr::operator())>> {
450  using type = TExpr;
451  template <class... Ts>
452  zero_wrapper(Ts &&...) {}
453  const TExpr &get() const { return reinterpret_cast<const TExpr &>(*this); }
454 };
455 namespace detail {
456 template <class, int N, int... Ns>
457 auto get_type_name(const char *ptr, index_sequence<Ns...>) {
458  static const char str[] = {ptr[N + Ns]..., 0};
459  return str;
460 }
461 }
462 template <class T>
463 const char *get_type_name() {
464 #if defined(COMPILING_WITH_MSVC)
465  return detail::get_type_name<T, 34>(__FUNCSIG__, make_index_sequence<sizeof(__FUNCSIG__) - 34 - 8>{});
466 #elif defined(__clang__)
467  return detail::get_type_name<T, 58>(__PRETTY_FUNCTION__, make_index_sequence<sizeof(__PRETTY_FUNCTION__) - 58 - 2>{});
468 #elif defined(__GNUC__)
469  return detail::get_type_name<T, 63>(__PRETTY_FUNCTION__, make_index_sequence<sizeof(__PRETTY_FUNCTION__) - 63 - 2>{});
470 #endif
471 }
472 template <class T, T...>
473 struct string;
474 template <char... Chrs>
475 struct string<char, Chrs...> {
476  using type = string;
477  static auto c_str() {
478  static constexpr char str[] = {Chrs..., 0};
479  return str;
480  }
481 };
482 template <class T>
483 struct string<T> {
484  using type = T;
485  static auto c_str() { return c_str_impl((T *)0); }
486  template <class U>
487  static decltype(U::c_str()) c_str_impl(U *) {
488  return U::c_str();
489  }
490  static auto c_str_impl(...) { return get_type_name<T>(); }
491 };
492 }
493 namespace back {
494 namespace policies {
495 struct defer_queue_policy__ {};
496 template <template <class...> class T>
497 struct defer_queue : aux::pair<back::policies::defer_queue_policy__, defer_queue<T>> {
498  template <class U>
499  using rebind = T<U>;
500  using flag = bool;
501 };
502 }
503 }
504 namespace back {
505 template <class... Ts>
506 class queue_event {
507  using ids_t = aux::type_id<Ts...>;
508  static constexpr auto alignment = aux::max<alignof(Ts)...>();
509  static constexpr auto size = aux::max<sizeof(Ts)...>();
510  template <class T>
511  static void dtor_impl(aux::byte *data) {
512  (void)data;
513  reinterpret_cast<T *>(data)->~T();
514  }
515  template <class T>
516  static void move_impl(aux::byte (&data)[size], queue_event &&other) {
517  new (&data) T(static_cast<T &&>(*reinterpret_cast<T *>(other.data)));
518  }
519 
520  public:
521  queue_event(queue_event &&other) : id(other.id), dtor(other.dtor), move(other.move) {
522  move(data, static_cast<queue_event &&>(other));
523  }
524  queue_event &operator=(queue_event &&other) {
525  dtor(data);
526 
527  id = other.id;
528  dtor = other.dtor;
529  move = other.move;
530  move(data, static_cast<queue_event &&>(other));
531  return *this;
532  }
533  queue_event(const queue_event &) = delete;
534  queue_event &operator=(const queue_event &) = delete;
535  template <class T>
536  queue_event(T object) {
537  id = aux::get_id<int, T>((ids_t *)0);
538  dtor = &dtor_impl<T>;
539  move = &move_impl<T>;
540  new (&data) T(static_cast<T &&>(object));
541  }
542  ~queue_event() { dtor(data); }
543  alignas(alignment) aux::byte data[size];
544  int id = -1;
545 
546  private:
547  void (*dtor)(aux::byte *);
548  void (*move)(aux::byte (&)[size], queue_event &&);
549 };
550 template <class TEvent>
551 class queue_event_call {
552  using call_t = void (*)(void *, const TEvent &);
553 
554  public:
555  queue_event_call() = default;
556  explicit queue_event_call(const call_t &call) : call{call} {}
557  call_t call{};
558 };
559 template <class... TEvents>
560 struct queue_handler : queue_event_call<TEvents>... {
561  queue_handler() = default;
562  template <class TQueue, class = typename TQueue::container_type>
563  explicit queue_handler(TQueue &queue)
564  : queue_event_call<TEvents>(queue_handler::push_impl<TQueue, TEvents>)..., queue_{&queue} {}
565  template <class TEvent>
566  void operator()(const TEvent &event) {
567  static_cast<queue_event_call<TEvent> *>(this)->call(queue_, event);
568  }
569 
570  private:
571  template <class TQueue, class TEvent>
572  static auto push_impl(void *queue, const TEvent &event) {
573  static_cast<TQueue *>(queue)->push(event);
574  }
575  void *queue_{};
576 };
577 template <class... TEvents>
578 struct deque_handler : queue_event_call<TEvents>... {
579  deque_handler() = default;
580  template <class TDeque, class = typename TDeque::allocator_type>
581  explicit deque_handler(TDeque &deque)
582  : queue_event_call<TEvents>(deque_handler::push_impl<TDeque, TEvents>)..., deque_{&deque} {}
583  template <class TEvent>
584  void operator()(const TEvent &event) {
585  static_cast<queue_event_call<TEvent> *>(this)->call(deque_, event);
586  }
587 
588  private:
589  template <class TDeque, class TEvent>
590  static auto push_impl(void *deque, const TEvent &event) {
591  static_cast<TDeque *>(deque)->push_back(event);
592  }
593  void *deque_{};
594 };
595 }
596 namespace back {
597 struct _ {};
598 struct initial {};
599 struct unexpected {};
600 struct entry_exit {};
601 struct terminate_state {
602  static auto c_str() { return "terminate"; }
603 };
604 struct internal_event {
605  static auto c_str() { return "internal_event"; }
606 };
607 struct anonymous : internal_event {
608  static auto c_str() { return "anonymous"; }
609 };
610 template <class T, class TEvent = T>
611 struct on_entry : internal_event, entry_exit {
612  static auto c_str() { return "on_entry"; }
613  explicit on_entry(const TEvent &event = {}) : event_(event) {}
614  const TEvent &event_;
615 };
616 template <class T, class TEvent = T>
617 struct on_exit : internal_event, entry_exit {
618  static auto c_str() { return "on_exit"; }
619  explicit on_exit(const TEvent &event = {}) : event_(event) {}
620  const TEvent &event_;
621 };
622 template <class T, class TException = T>
623 struct exception : internal_event {
624  using type = TException;
625  explicit exception(const TException &exception = {}) : exception_(exception) {}
626  const TException &exception_;
627 };
628 template <class T, class TEvent = T>
629 struct unexpected_event : internal_event, unexpected {
630  explicit unexpected_event(const TEvent &event = {}) : event_(event) {}
631  const TEvent &event_;
632 };
633 template <class TEvent>
634 struct event_type {
635  using event_t = TEvent;
636  using generic_t = TEvent;
637  using mapped_t = void;
638 };
639 template <class TEvent>
640 struct event_type<exception<TEvent>> {
641  using event_t = TEvent;
642  using generic_t = exception<TEvent>;
643  using mapped_t = void;
644 };
645 template <class TEvent, class T>
646 struct event_type<unexpected_event<T, TEvent>> {
647  using event_t = TEvent;
648  using generic_t = unexpected_event<T>;
649  using mapped_t = void;
650 };
651 template <class TEvent, class T>
652 struct event_type<on_entry<T, TEvent>> {
653  using event_t = TEvent;
654  using generic_t = on_entry<T>;
655  using mapped_t = on_entry<T, TEvent>;
656 };
657 template <class TEvent, class T>
658 struct event_type<on_exit<T, TEvent>> {
659  using event_t = TEvent;
660  using generic_t = on_exit<T>;
661  using mapped_t = on_exit<T, TEvent>;
662 };
663 template <class TEvent>
664 using get_event_t = typename event_type<TEvent>::event_t;
665 template <class TEvent>
666 using get_generic_t = typename event_type<TEvent>::generic_t;
667 template <class TEvent>
668 using get_mapped_t = typename event_type<TEvent>::mapped_t;
669 template <class... TEvents>
670 struct process : queue_handler<TEvents...> {
671  using queue_handler<TEvents...>::queue_handler;
672 };
673 template <class... TEvents>
674 struct defer : deque_handler<TEvents...> {
675  using deque_handler<TEvents...>::deque_handler;
676 };
677 }
678 namespace back {
679 template <class>
680 class sm;
681 template <class>
682 struct sm_impl;
683 template <class, class...>
684 struct sm_policy;
685 template <class TEvent>
686 using get_event = aux::conditional_t<aux::is_base_of<internal_event, TEvent>::value, aux::type_list<>, aux::type_list<TEvent>>;
687 template <class, class, class TEvent>
688 struct get_all_events_impl {
689  using type = get_event<TEvent>;
690 };
691 template <class TSrc, class TDst, class TEvent>
692 struct get_all_events_impl<TSrc, TDst, unexpected_event<TEvent>> {
693  using type = aux::type_list<TEvent>;
694 };
695 template <class TSrc, class TDst, class TEvent>
696 struct get_all_events_impl<sm<TSrc>, TDst, TEvent> {
697  using type = aux::join_t<get_event<TEvent>, typename sm<TSrc>::events>;
698 };
699 template <class TSrc, class TDst, class TEvent>
700 struct get_all_events_impl<TSrc, sm<TDst>, TEvent> {
701  using type = aux::join_t<get_event<TEvent>, typename sm<TDst>::events>;
702 };
703 template <class TSrc, class TDst, class TEvent>
704 struct get_all_events_impl<sm<TSrc>, sm<TDst>, TEvent> {
705  using type = aux::join_t<get_event<TEvent>, typename sm<TSrc>::events, typename sm<TDst>::events>;
706 };
707 template <class, class TEvent>
708 struct get_sub_internal_events_impl {
709  using type = aux::conditional_t<aux::is_base_of<internal_event, TEvent>::value, aux::type_list<TEvent>, aux::type_list<>>;
710 };
711 template <class T, class TEvent>
712 struct get_sub_internal_events_impl<sm<T>, TEvent> {
713  using type = aux::join_t<aux::type_list<TEvent>, typename sm_impl<T>::sub_internal_events_t>;
714 };
715 template <class... Ts>
716 using get_all_events =
717  aux::join_t<typename get_all_events_impl<typename Ts::src_state, typename Ts::dst_state, typename Ts::event>::type...>;
718 template <class... Ts>
719 using get_sub_internal_events =
720  aux::join_t<typename get_sub_internal_events_impl<typename Ts::src_state, typename Ts::event>::type...,
721  typename get_sub_internal_events_impl<typename Ts::dst_state, typename Ts::event>::type...>;
722 template <class... Ts>
723 using get_events = aux::type_list<typename Ts::event...>;
724 template <class T>
725 struct get_exception : aux::type_list<> {};
726 template <class T>
727 struct get_exception<exception<T>> : aux::type_list<exception<T>> {};
728 template <class... Ts>
729 using get_exceptions = aux::join_t<typename get_exception<Ts>::type...>;
730 template <class... Ts>
731 using get_states = aux::join_t<aux::type_list<typename Ts::src_state, typename Ts::dst_state>...>;
732 template <class... Ts>
733 using get_initial_states =
734  aux::join_t<typename aux::conditional<Ts::initial, aux::type_list<typename Ts::src_state>, aux::type_list<>>::type...>;
735 template <class... Ts>
736 using get_history_states = aux::join_t<
737  typename aux::conditional<!Ts::history && Ts::initial, aux::type_list<typename Ts::src_state>, aux::type_list<>>::type...>;
738 template <class>
739 struct get_sub_sm : aux::type_list<> {};
740 template <class T>
741 struct get_sub_sm<sm<T>> : aux::join_t<aux::type_list<T>, typename sm<T>::state_machines> {};
742 template <class... Ts>
743 using get_sub_sms = aux::join_t<typename get_sub_sm<Ts>::type...>;
744 template <class... Ts>
745 using get_sm_t = aux::type_list<typename Ts::sm...>;
746 template <class... Ts>
747 using get_non_empty_t =
748  aux::join_t<typename aux::conditional<aux::is_empty<Ts>::value, aux::type_list<>, aux::type_list<Ts>>::type...>;
749 template <class... Ts>
750 using merge_deps = aux::join_t<typename Ts::deps...>;
751 template <class>
752 struct sub_sm;
753 template <class T>
754 struct sub_sm<sm_impl<sm_policy<T>>> {
755  template <class U, class... TPolicies>
756  static sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>> &get(
757  aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>>> *object) {
758  return static_cast<aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>>> &>(*object).value;
759  }
760  template <class... TPolicies>
761  static sm_impl<sm_policy<T, TPolicies...>> &get(aux::pool_type<sm_impl<sm_policy<T, TPolicies...>>> *object) {
762  return static_cast<aux::pool_type<sm_impl<sm_policy<T, TPolicies...>>> &>(*object).value;
763  }
764  template <class... TPolicies>
765  static const sm_impl<sm_policy<T, TPolicies...>> &cget(const aux::pool_type<sm_impl<sm_policy<T, TPolicies...>>> *object) {
766  return static_cast<const aux::pool_type<sm_impl<sm_policy<T, TPolicies...>>> &>(*object).value;
767  }
768 };
769 template <class T, class U>
770 struct sub_sm<sm_impl<sm_policy<T, aux::identity<U>>>> {
771  template <class... TPolicies>
772  static sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>> &get(
773  aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>>> *object) {
774  return static_cast<aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>>> &>(*object).value;
775  }
776  template <class... TPolicies>
777  static const sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>> &cget(
778  const aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>>> *object) {
779  return static_cast<const aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>>> &>(*object).value;
780  }
781 };
782 template <class T, class... TPolicies>
783 struct rebind_impl {
784  using type = sm_policy<T, TPolicies...>;
785 };
786 template <class T, class... TDetails, class... TPolicies>
787 struct rebind_impl<sm_policy<T, TDetails...>, TPolicies...> {
788  using type = sm_policy<T, TDetails..., TPolicies...>;
789 };
790 template <class T, class... TDetails, class... TPolicies>
791 struct rebind_impl<sm<sm_policy<T, TDetails...>>, TPolicies...> {
792  using type = sm_policy<T, TDetails..., TPolicies...>;
793 };
794 template <class, class>
795 struct convert_to_sm;
796 template <class T, class... Ts>
797 struct convert_to_sm<T, aux::type_list<Ts...>> {
798  using type = aux::type_list<sm_impl<T>, sm_impl<typename T::template rebind<Ts>>...>;
799 };
800 }
801 namespace back {
802 template <class>
803 class sm;
804 template <class>
805 struct sm_impl;
806 template <class...>
807 struct transitions;
808 template <class...>
809 struct transitions_sub;
810 template <class T, class... Ts>
811 struct transitions<T, Ts...> {
812  template <class TEvent, class SM, class TDeps, class TSubs>
813  static bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state) {
814  if (aux::get<T>(sm.transitions_).execute(event, sm, deps, subs, current_state, typename SM::has_entry_exits{})) {
815  return true;
816  }
817  return transitions<Ts...>::execute(event, sm, deps, subs, current_state);
818  }
819 };
820 template <class T>
821 struct transitions<T> {
822  template <class TEvent, class SM, class TDeps, class TSubs>
823  static bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state) {
824  return execute_impl(event, sm, deps, subs, current_state);
825  }
826  template <class TEvent, class SM, class TDeps, class TSubs>
827  static bool execute_impl(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state) {
828  return aux::get<T>(sm.transitions_).execute(event, sm, deps, subs, current_state, typename SM::has_entry_exits{});
829  }
830  template <class _, class TEvent, class SM, class TDeps, class TSubs>
831  static bool execute_impl(const on_exit<_, TEvent> &event, SM &sm, TDeps &deps, TSubs &subs,
832  typename SM::state_t &current_state) {
833  aux::get<T>(sm.transitions_).execute(event, sm, deps, subs, current_state, typename SM::has_entry_exits{});
834  return false;
835  }
836 };
837 template <>
838 struct transitions<aux::true_type> {
839  template <class TEvent, class SM, class TDeps, class TSubs>
840  static bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state) {
841  sm.process_internal_event(unexpected_event<TEvent>{event}, deps, subs, current_state);
842  return false;
843  }
844 };
845 template <>
846 struct transitions<aux::false_type> {
847  template <class TEvent, class SM, class TDeps, class TSubs>
848  static bool execute(const TEvent &, SM &, TDeps &, TSubs &, typename SM::state_t &) {
849  return false;
850  }
851 };
852 template <class TSM, class T, class... Ts>
853 struct transitions_sub<sm<TSM>, T, Ts...> {
854  template <class TEvent, class SM, class TDeps, class TSubs>
855  static bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state) {
856  return execute_impl(event, sm, deps, subs, current_state);
857  }
858  template <class, class SM, class TDeps, class TSubs>
859  static bool execute(const anonymous &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state) {
860  if (sub_sm<sm_impl<TSM>>::cget(&subs).is_terminated()) {
861  const auto handled = sub_sm<sm_impl<TSM>>::get(&subs).process_event(event, deps, subs);
862  return handled ? handled : transitions<T, Ts...>::execute(event, sm, deps, subs, current_state);
863  }
864  return false;
865  }
866  template <class TEvent, class SM, class TDeps, class TSubs>
867  static bool execute_impl(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state) {
868  const auto handled = sub_sm<sm_impl<TSM>>::get(&subs).process_event(event, deps, subs);
869  return handled ? handled : transitions<T, Ts...>::execute(event, sm, deps, subs, current_state);
870  }
871  template <class _, class TEvent, class SM, class TDeps, class TSubs>
872  static bool execute_impl(const back::on_entry<_, TEvent> &event, SM &sm, TDeps &deps, TSubs &subs,
873  typename SM::state_t &current_state) {
874  transitions<T, Ts...>::execute(event, sm, deps, subs, current_state);
875  sub_sm<sm_impl<TSM>>::get(&subs).process_event(event, deps, subs);
876  return true;
877  }
878 };
879 template <class TSM>
880 struct transitions_sub<sm<TSM>> {
881  template <class TEvent, class SM, class TDeps, class TSubs>
882  static bool execute(const TEvent &event, SM &, TDeps &deps, TSubs &subs, typename SM::state_t &) {
883  return sub_sm<sm_impl<TSM>>::get(&subs).template process_event<TEvent>(event, deps, subs);
884  }
885 };
886 }
887 namespace back {
888 template <class>
889 class sm;
890 template <class>
891 struct state;
892 template <class>
893 struct event;
894 template <class...>
895 struct transitions;
896 template <class...>
897 struct transitions_sub;
898 template <class, class>
899 struct state_mappings;
900 template <class S, class... Ts>
901 struct state_mappings<S, aux::type_list<Ts...>> {
902  using element_type = state<S>;
903  using types = aux::type_list<Ts...>;
904 };
905 template <class, class>
906 struct event_mappings;
907 template <class E, class... Ts>
908 struct event_mappings<E, aux::inherit<Ts...>> {
909  using element_type = event<E>;
910  using types = aux::type_list<Ts...>;
911 };
912 template <class...>
913 struct unique_mappings;
914 template <class, class...>
915 struct unique_mappings_impl;
916 template <class... Ts>
917 using unique_mappings_t = typename unique_mappings<Ts...>::type;
918 template <class, class, class, class R>
919 struct get_mapping : aux::type_list<R> {};
920 template <class E, class T, class R>
921 struct get_mapping<event<E>, event<E>, T, R>
922  : aux::type_list<event_mappings<E, aux::apply_t<unique_mappings_t, aux::join_t<typename R::types, typename T::types>>>> {};
923 template <class S, class T, class R>
924 struct get_mapping<state<S>, state<S>, T, R>
925  : aux::type_list<state_mappings<S, aux::join_t<typename R::types, typename T::types>>> {};
926 template <class T, class... Ts>
927 struct extend_mapping : aux::join_t<typename get_mapping<typename T::element_type, typename Ts::element_type, T, Ts>::type...> {
928 };
929 template <class T, class... Ts>
930 using extend_mapping_t = aux::apply_t<aux::inherit, typename extend_mapping<T, Ts...>::type>;
931 template <bool, class, class...>
932 struct conditional_mapping;
933 template <class T1, class T2, class... Rs, class... Ts>
934 struct conditional_mapping<true, aux::type<T1, aux::inherit<Rs...>>, T2, Ts...> {
935  using type = unique_mappings_impl<aux::type<aux::inherit<T1>, extend_mapping_t<T2, Rs...>>, Ts...>;
936 };
937 template <class T1, class T2, class... Rs, class... Ts>
938 struct conditional_mapping<false, aux::type<T1, aux::inherit<Rs...>>, T2, Ts...> {
939  using type =
940  unique_mappings_impl<aux::type<aux::inherit<T1, aux::type<typename T2::element_type>>, aux::inherit<T2, Rs...>>, Ts...>;
941 };
942 template <class T1, class T2, class... Rs, class... Ts>
943 struct unique_mappings_impl<aux::type<T1, aux::inherit<Rs...>>, T2, Ts...>
944  : conditional_mapping<aux::is_base_of<aux::type<typename T2::element_type>, T1>::value, aux::type<T1, aux::inherit<Rs...>>,
945  T2, Ts...>::type {};
946 template <class T1, class Rs>
947 struct unique_mappings_impl<aux::type<T1, Rs>> : aux::apply_t<aux::inherit, Rs> {};
948 template <class... Ts>
949 struct unique_mappings : unique_mappings_impl<aux::type<aux::none_type, aux::inherit<>>, Ts...> {};
950 template <class T>
951 struct unique_mappings<T> : aux::inherit<T> {};
952 template <class, class...>
953 struct mappings;
954 template <class... Ts>
955 struct mappings<aux::pool<Ts...>>
956  : unique_mappings_t<
957  event_mappings<typename Ts::event, aux::inherit<state_mappings<typename Ts::src_state, aux::type_list<Ts>>>>...> {};
958 template <class T>
959 using mappings_t = typename mappings<T>::type;
960 template <class, class TUnexpected>
961 transitions<TUnexpected> get_state_mapping_impl(...);
962 template <class T, class, class... Ts>
963 transitions<Ts...> get_state_mapping_impl(state_mappings<T, aux::type_list<Ts...>> *);
964 template <class T, class TMappings, class TUnexpected>
965 struct get_state_mapping {
966  using type = decltype(get_state_mapping_impl<T, TUnexpected>((TMappings *)0));
967 };
968 template <class S>
969 transitions_sub<S> get_sub_state_mapping_impl(...);
970 template <class T, class... Ts>
971 transitions_sub<T, Ts...> get_sub_state_mapping_impl(state_mappings<T, aux::type_list<Ts...>> *);
972 template <class T, class TMappings, class TUnexpected>
973 struct get_state_mapping<sm<T>, TMappings, TUnexpected> {
974  using type = decltype(get_sub_state_mapping_impl<sm<T>>((TMappings *)0));
975 };
976 template <class T, class TMappings, class TUnexpected>
977 using get_state_mapping_t = typename get_state_mapping<T, TMappings, TUnexpected>::type;
978 template <class>
979 transitions<aux::true_type> get_event_mapping_impl(...);
980 template <class T, class TMappings>
981 TMappings get_event_mapping_impl(event_mappings<T, TMappings> *);
982 template <class T, class... T1Mappings, class... T2Mappings>
983 unique_mappings_t<T1Mappings..., T2Mappings...> get_event_mapping_impl(event_mappings<T, aux::inherit<T1Mappings...>> *,
984  event_mappings<_, aux::inherit<T2Mappings...>> *);
985 template <class T, class TMappings>
986 struct get_event_mapping_impl_helper
987  : aux::conditional<aux::is_same<transitions<aux::true_type>, decltype(get_event_mapping_impl<_>((TMappings *)0))>::value,
988  decltype(get_event_mapping_impl<T>((TMappings *)0)),
989  decltype(get_event_mapping_impl<T>((TMappings *)0, (TMappings *)0))>::type {};
990 template <class T, class TMappings>
991 struct get_event_mapping_impl_helper<exception<T>, TMappings> : decltype(get_event_mapping_impl<exception<T>>((TMappings *)0)) {
992 };
993 template <class T1, class T2, class TMappings>
994 struct get_event_mapping_impl_helper<unexpected_event<T1, T2>, TMappings>
995  : decltype(get_event_mapping_impl<unexpected_event<T1, T2>>((TMappings *)0)) {};
996 template <class T1, class T2, class TMappings>
997 struct get_event_mapping_impl_helper<on_entry<T1, T2>, TMappings>
998  : decltype(get_event_mapping_impl<on_entry<T1, T2>>((TMappings *)0)) {};
999 template <class T1, class T2, class TMappings>
1000 struct get_event_mapping_impl_helper<on_exit<T1, T2>, TMappings>
1001  : decltype(get_event_mapping_impl<on_exit<T1, T2>>((TMappings *)0)) {};
1002 template <class T, class TMappings>
1003 using get_event_mapping_t = get_event_mapping_impl_helper<T, TMappings>;
1004 }
1005 namespace back {
1006 namespace policies {
1007 struct dispatch_policy__ {};
1008 template <class T>
1009 struct dispatch : aux::pair<dispatch_policy__, T> {
1010  using type = T;
1011 };
1012 struct jump_table {
1013  template <int, class TMappings, class sm_impl, class State, class TEvent, class TDeps, class TSubs>
1014  static bool dispatch(sm_impl &, State &, const TEvent &, TDeps &, TSubs &, const aux::type_list<> &) {
1015  return false;
1016  }
1017  template <int, class TMappings, class sm_impl, class State, class TEvent, class TDeps, class TSubs, class... TStates>
1018  static bool dispatch(sm_impl &self, State &current_state, const TEvent &event, TDeps &deps, TSubs &subs,
1019  const aux::type_list<TStates...> &) {
1020  using dispatch_table_t = bool (*)(const TEvent &, sm_impl &, TDeps &, TSubs &, State &);
1021  constexpr static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(sizeof...(TStates))] = {
1022  &get_state_mapping_t<TStates, TMappings, typename sm_impl::has_unexpected_events>::template execute<TEvent, sm_impl,
1023  TDeps, TSubs>...};
1024  return dispatch_table[current_state](event, self, deps, subs, current_state);
1025  }
1026 };
1027 struct branch_stm {
1028  template <int, class TMappings, class sm_impl, class State, class TEvent, class TDeps, class TSubs>
1029  static bool dispatch(sm_impl &, State &, const TEvent &, TDeps &, TSubs &, const aux::type_list<> &) {
1030  return false;
1031  }
1032  template <int N, class TMappings, class sm_impl, class State, class TEvent, class TDeps, class TSubs, class TState,
1033  class... TStates>
1034  static bool dispatch(sm_impl &self, State &current_state, const TEvent &event, TDeps &deps, TSubs &subs,
1035  const aux::type_list<TState, TStates...> &) {
1036  return current_state == N
1037  ? get_state_mapping_t<TState, TMappings, typename sm_impl::has_unexpected_events>::template execute<
1038  TEvent, sm_impl, TDeps, TSubs>(event, self, deps, subs, current_state)
1039  : dispatch<N + 1, TMappings>(self, current_state, event, deps, subs, aux::type_list<TStates...>{});
1040  }
1041 };
1042 struct switch_stm {
1043  template <int, class TMappings, class sm_impl, class State, class TEvent, class TDeps, class TSubs>
1044  static bool dispatch(sm_impl &, State &, const TEvent &, TDeps &, TSubs &, const aux::type_list<> &) {
1045  return false;
1046  }
1047  template <int N, class TMappings, class sm_impl, class State, class TEvent, class TDeps, class TSubs, class TState,
1048  class... TStates>
1049  static bool dispatch(sm_impl &self, State &current_state, const TEvent &event, TDeps &deps, TSubs &subs,
1050  const aux::type_list<TState, TStates...> &) {
1051  switch (current_state) {
1052  case N:
1053  return get_state_mapping_t<TState, TMappings, typename sm_impl::has_unexpected_events>::template execute<
1054  TEvent, sm_impl, TDeps, TSubs>(event, self, deps, subs, current_state);
1055  default:
1056  return dispatch<N + 1, TMappings>(self, current_state, event, deps, subs, aux::type_list<TStates...>{});
1057  }
1058  }
1059 };
1060 #if defined(__cpp_fold_expressions)
1061 struct fold_expr {
1062  template <class TMappings, int... Ns, class sm_impl, class State, class TEvent, class TDeps, class TSubs, class... TStates>
1063  static bool dispatch_impl(sm_impl &self, State &current_state, aux::index_sequence<Ns...>, const TEvent &event, TDeps &deps,
1064  TSubs &subs, const aux::type_list<TStates...> &) {
1065  return ((current_state == Ns
1066  ? get_state_mapping_t<TStates, TMappings, typename sm_impl::has_unexpected_events>::template execute<
1067  TEvent, sm_impl, TDeps, TSubs>(event, self, deps, subs, current_state)
1068  : false) ||
1069  ...);
1070  }
1071  template <int N, class TMappings, class sm_impl, class State, class TEvent, class TDeps, class TSubs, class... TStates>
1072  static bool dispatch(sm_impl &self, State &current_state, const TEvent &event, TDeps &deps, TSubs &subs,
1073  const aux::type_list<TStates...> &states) {
1074  return dispatch_impl<TMappings>(self, current_state, aux::make_index_sequence<sizeof...(TStates)>{}, event, deps, subs,
1075  states);
1076  }
1077 };
1078 #endif
1079 }
1080 }
1081 namespace back {
1082 template <class>
1083 class sm;
1084 template <class, class...>
1085 struct sm_policy;
1086 struct no_policy;
1087 namespace policies {
1088 struct logger_policy__ {};
1089 template <class T>
1090 struct logger : aux::pair<logger_policy__, logger<T>> {
1091  using type = T;
1092 };
1093 template <class>
1094 struct get_state_name;
1095 template <class T>
1096 struct get_state_name<aux::string<T>> {
1097  using type = aux::string<T>;
1098 };
1099 template <class T, class... Ts>
1100 struct get_state_name<aux::string<sm<sm_policy<T, Ts...>>>> {
1101  using type = typename get_state_name<aux::string<sm_policy<T, Ts...>>>::type;
1102 };
1103 template <class T>
1104 struct get_state_name<aux::string<sm_policy<T>>> {
1105  using type = aux::string<T>;
1106 };
1107 template <class T, class TName>
1108 struct get_state_name<aux::string<sm_policy<T, TName>>> {
1109  using type = aux::string<T(typename TName::type)>;
1110 };
1111 template <class T>
1112 using get_state_name_t = typename get_state_name<T>::type;
1113 template <class, class TDeps, class TEvent>
1114 void log_process_event(const aux::type<no_policy> &, TDeps &, const TEvent &) {}
1115 template <class SM, class TLogger, class TDeps, class TEvent>
1116 void log_process_event(const aux::type<TLogger> &, TDeps &deps, const TEvent &event) {
1117  return static_cast<aux::pool_type<TLogger &> &>(deps).value.template log_process_event<SM>(event);
1118 }
1119 template <class, class TDeps, class TSrcState, class TDstState>
1120 void log_state_change(const aux::type<no_policy> &, TDeps &, const TSrcState &, const TDstState &) {}
1121 template <class SM, class TLogger, class TDeps, class TSrcState, class TDstState>
1122 void log_state_change(const aux::type<TLogger> &, TDeps &deps, const TSrcState &, const TDstState &) {
1123  return static_cast<aux::pool_type<TLogger &> &>(deps).value.template log_state_change<SM>(get_state_name_t<TSrcState>{},
1124  get_state_name_t<TDstState>{});
1125 }
1126 template <class, class TDeps, class TAction, class TEvent>
1127 void log_action(const aux::type<no_policy> &, TDeps &, const TAction &, const TEvent &) {}
1128 template <class SM, class TLogger, class TDeps, class TAction, class TEvent>
1129 void log_action(const aux::type<TLogger> &, TDeps &deps, const TAction &action, const TEvent &event) {
1130  return static_cast<aux::pool_type<TLogger &> &>(deps).value.template log_action<SM>(action, event);
1131 }
1132 template <class SM, class TLogger, class TDeps, class TAction, class TEvent>
1133 void log_action(const aux::type<TLogger> &, TDeps &deps, const aux::zero_wrapper<TAction> &action, const TEvent &event) {
1134  return static_cast<aux::pool_type<TLogger &> &>(deps).value.template log_action<SM>(action.get(), event);
1135 }
1136 template <class, class TDeps, class TGuard, class TEvent>
1137 void log_guard(const aux::type<no_policy> &, TDeps &, const TGuard &, const TEvent &, bool) {}
1138 template <class SM, class TLogger, class TDeps, class TGuard, class TEvent>
1139 void log_guard(const aux::type<TLogger> &, TDeps &deps, const TGuard &guard, const TEvent &event, bool result) {
1140  return static_cast<aux::pool_type<TLogger &> &>(deps).value.template log_guard<SM>(guard, event, result);
1141 }
1142 template <class SM, class TLogger, class TDeps, class TGuard, class TEvent>
1143 void log_guard(const aux::type<TLogger> &, TDeps &deps, const aux::zero_wrapper<TGuard> &guard, const TEvent &event,
1144  bool result) {
1145  return static_cast<aux::pool_type<TLogger &> &>(deps).value.template log_guard<SM>(guard.get(), event, result);
1146 }
1147 }
1148 }
1149 namespace back {
1150 namespace policies {
1151 struct process_queue_policy__ {};
1152 template <template <class...> class T>
1153 struct process_queue : aux::pair<back::policies::process_queue_policy__, process_queue<T>> {
1154  template <class U>
1155  using rebind = T<U>;
1156 };
1157 }
1158 }
1159 namespace back {
1160 namespace policies {
1161 struct testing_policy__ {};
1162 struct testing : aux::pair<testing_policy__, testing> {};
1163 }
1164 }
1165 namespace back {
1166 namespace policies {
1167 struct thread_safety_policy__ {
1168  auto create_lock() { return *this; }
1169  __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
1170 };
1171 template <class TLock>
1172 struct thread_safe : aux::pair<thread_safety_policy__, thread_safe<TLock>> {
1173  using type = thread_safe;
1174  auto create_lock() {
1175  struct lock_guard {
1176  explicit lock_guard(TLock &lock) : lock_{lock} { lock_.lock(); }
1177  ~lock_guard() { lock_.unlock(); }
1178  TLock &lock_;
1179  };
1180  return lock_guard{lock};
1181  }
1182  TLock lock;
1183 };
1184 }
1185 }
1186 namespace back {
1187 struct no_policy : policies::thread_safety_policy__ {
1188  using type = no_policy;
1189  template <class>
1190  using rebind = no_policy;
1191  template <class...>
1192  using defer = no_policy;
1193  using const_iterator = no_policy;
1194  using flag = no_policy;
1195  __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
1196 };
1197 template <class TDefault, class>
1198 TDefault get_policy(...);
1199 template <class, class T, class TPolicy>
1200 TPolicy get_policy(aux::pair<T, TPolicy> *);
1201 template <class SM, class... TPolicies>
1202 struct sm_policy {
1203  static_assert(aux::is_same<aux::remove_reference_t<SM>, SM>::value, "SM type can't have qualifiers");
1204 #if defined(COMPILING_WITH_MSVC)
1205  using default_dispatch_policy = policies::jump_table;
1206 #elif defined(__clang__)
1207  using default_dispatch_policy = policies::jump_table;
1208 #elif defined(__GNUC__)
1209  using default_dispatch_policy = policies::branch_stm;
1210 #endif
1211  using sm = SM;
1212  using thread_safety_policy =
1213  decltype(get_policy<no_policy, policies::thread_safety_policy__>((aux::inherit<TPolicies...> *)0));
1214  using defer_queue_policy = decltype(get_policy<no_policy, policies::defer_queue_policy__>((aux::inherit<TPolicies...> *)0));
1215  using process_queue_policy =
1216  decltype(get_policy<no_policy, policies::process_queue_policy__>((aux::inherit<TPolicies...> *)0));
1217  using logger_policy = decltype(get_policy<no_policy, policies::logger_policy__>((aux::inherit<TPolicies...> *)0));
1218  using testing_policy = decltype(get_policy<no_policy, policies::testing_policy__>((aux::inherit<TPolicies...> *)0));
1219  using dispatch_policy =
1220  decltype(get_policy<default_dispatch_policy, policies::dispatch_policy__>((aux::inherit<TPolicies...> *)0));
1221  template <class T>
1222  using rebind = typename rebind_impl<T, TPolicies...>::type;
1223 };
1224 }
1225 namespace concepts {
1226 struct callable_fallback {
1227  void operator()();
1228 };
1229 template <class T>
1230 aux::false_type test_callable(aux::non_type<void (callable_fallback::*)(), &T::operator()> *);
1231 template <class>
1232 aux::true_type test_callable(...);
1233 template <class, class T>
1234 struct callable
1235  : decltype(test_callable<aux::inherit<aux::conditional_t<__is_class(T), T, aux::none_type>, callable_fallback>>(0)) {};
1236 }
1237 namespace concepts {
1238 template <class T>
1239 decltype(aux::declval<T>().operator()()) composable_impl(int);
1240 template <class>
1241 void composable_impl(...);
1242 template <class T>
1243 struct composable : aux::is<aux::pool, decltype(composable_impl<T>(0))> {};
1244 }
1245 #if !defined(BOOST_SML_DISABLE_EXCEPTIONS)
1246 #if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND))
1247 #define BOOST_SML_DISABLE_EXCEPTIONS true
1248 #else
1249 #define BOOST_SML_DISABLE_EXCEPTIONS false
1250 #endif
1251 #endif
1252 namespace back {
1253 template <class TSM>
1254 struct sm_impl : aux::conditional_t<aux::is_empty<typename TSM::sm>::value, aux::none_type, typename TSM::sm> {
1255  using sm_t = typename TSM::sm;
1256  using thread_safety_t = typename TSM::thread_safety_policy::type;
1257  template <class T>
1258  using defer_queue_t = typename TSM::defer_queue_policy::template rebind<T>;
1259  using defer_flag_t = typename TSM::defer_queue_policy::flag;
1260  template <class T>
1261  using process_queue_t = typename TSM::process_queue_policy::template rebind<T>;
1262  using logger_t = typename TSM::logger_policy::type;
1263  using dispatch_t = typename TSM::dispatch_policy;
1264  using transitions_t = decltype(aux::declval<sm_t>().operator()());
1265  using states_t = aux::apply_t<aux::unique_t, aux::apply_t<get_states, transitions_t>>;
1266  using states_ids_t = aux::apply_t<aux::type_id, states_t>;
1267  using initial_states_t = aux::apply_t<aux::unique_t, aux::apply_t<get_initial_states, transitions_t>>;
1268  using initial_states_ids_t = aux::apply_t<aux::type_id, initial_states_t>;
1269  using history_states_t = aux::apply_t<get_history_states, transitions_t>;
1270  using has_history_states =
1271  aux::integral_constant<bool, aux::size<initial_states_t>::value != aux::size<history_states_t>::value>;
1272  using sub_internal_events_t = aux::apply_t<get_sub_internal_events, transitions_t>;
1273  using events_t = aux::apply_t<aux::unique_t, aux::join_t<sub_internal_events_t, aux::apply_t<get_all_events, transitions_t>>>;
1274  using events_ids_t = aux::apply_t<aux::inherit, events_t>;
1275  using has_unexpected_events = typename aux::is_base_of<unexpected, aux::apply_t<aux::inherit, events_t>>::type;
1276  using has_entry_exits = typename aux::is_base_of<entry_exit, aux::apply_t<aux::inherit, events_t>>::type;
1277  using defer_t = defer_queue_t<aux::apply_t<queue_event, events_t>>;
1278  using process_t = process_queue_t<aux::apply_t<queue_event, events_t>>;
1279  using deps = aux::apply_t<merge_deps, transitions_t>;
1280  using state_t = aux::conditional_t<(aux::size<states_t>::value > 0xFF), unsigned short, aux::byte>;
1281  static constexpr auto regions = aux::size<initial_states_t>::value;
1282  static_assert(regions > 0, "At least one initial state is required");
1283 #if !BOOST_SML_DISABLE_EXCEPTIONS
1284  using exceptions = aux::apply_t<aux::unique_t, aux::apply_t<get_exceptions, events_t>>;
1285  using has_exceptions = aux::integral_constant<bool, (aux::size<exceptions>::value > 0)>;
1286 #endif
1287  struct mappings : mappings_t<transitions_t> {};
1288  template <class TPool>
1289  sm_impl(aux::init, const TPool &p) : sm_impl{p, aux::is_empty<sm_t>{}} {}
1290  template <class TPool>
1291  sm_impl(const TPool &p, aux::false_type) : sm_t{aux::try_get<sm_t>(&p)}, transitions_{(*this)()} {
1292  initialize(typename sm_impl<TSM>::initial_states_t{});
1293  }
1294  template <class TPool>
1295  sm_impl(const TPool &p, aux::true_type) : transitions_{aux::try_get<sm_t>(&p)()} {
1296  initialize(typename sm_impl<TSM>::initial_states_t{});
1297  }
1298  template <class TEvent, class TDeps, class TSubs>
1299  bool process_event(const TEvent &event, TDeps &deps, TSubs &subs) {
1300  policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1301 #if BOOST_SML_DISABLE_EXCEPTIONS
1302  const auto handled = process_event_impl<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(
1303  event, deps, subs, states_t{}, aux::make_index_sequence<regions>{});
1304 #else
1305  const auto handled =
1306  process_event_noexcept<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(event, deps, subs, has_exceptions{});
1307 #endif
1308  do {
1309  while (process_internal_events(anonymous{}, deps, subs)) {
1310  }
1311  process_defer_events(deps, subs, handled, aux::type<defer_queue_t<TEvent>>{}, events_t{});
1312  } while (process_queued_events(deps, subs, aux::type<process_queue_t<TEvent>>{}, events_t{}) ||
1313  process_internal_events(anonymous{}, deps, subs));
1314  return handled;
1315  }
1316  void initialize(const aux::type_list<> &) {}
1317  template <class TState>
1318  void initialize(const aux::type_list<TState> &) {
1319  current_state_[0] = aux::get_id<state_t, TState>((states_ids_t *)0);
1320  }
1321  template <class... TStates>
1322  void initialize(const aux::type_list<TStates...> &) {
1323  auto region = 0;
1324 #if defined(__cpp_fold_expressions)
1325  ((current_state_[region++] = aux::get_id<state_t, TStates>((states_ids_t *)0)), ...);
1326 #else
1327  (void)aux::swallow{0, (current_state_[region++] = aux::get_id<state_t, TStates>((states_ids_t *)0), 0)...};
1328 #endif
1329  }
1330  template <class TDeps, class TSubs>
1331  void start(TDeps &deps, TSubs &subs) {
1332  process_internal_events(on_entry<_, initial>{}, deps, subs);
1333  do {
1334  while (process_internal_events(anonymous{}, deps, subs)) {
1335  }
1336  process_defer_events(deps, subs, true, aux::type<defer_queue_t<initial>>{}, events_t{});
1337  } while (process_queued_events(deps, subs, aux::type<process_queue_t<initial>>{}, events_t{}) ||
1338  process_internal_events(anonymous{}, deps, subs));
1339  }
1340  template <class TEvent, class TDeps, class TSubs, class... Ts,
1341  __BOOST_SML_REQUIRES(!aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value &&
1342  !aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1343  bool process_internal_events(const TEvent &, TDeps &, TSubs &, Ts &&...) {
1344  return false;
1345  }
1346  template <class TEvent, class TDeps, class TSubs,
1347  __BOOST_SML_REQUIRES(aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value &&
1348  !aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1349  bool process_internal_events(const TEvent &event, TDeps &deps, TSubs &subs) {
1350  policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1351 #if BOOST_SML_DISABLE_EXCEPTIONS
1352  return process_event_impl<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(event, deps, subs, states_t{},
1353  aux::make_index_sequence<regions>{});
1354 #else
1355  return process_event_noexcept<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(event, deps, subs, has_exceptions{});
1356 #endif
1357  }
1358  template <class TEvent, class TDeps, class TSubs,
1359  __BOOST_SML_REQUIRES(aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1360  bool process_internal_events(const TEvent &event, TDeps &deps, TSubs &subs) {
1361  policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1362 #if BOOST_SML_DISABLE_EXCEPTIONS
1363  return process_event_impl<get_event_mapping_t<get_mapped_t<TEvent>, mappings>>(event, deps, subs, states_t{},
1364  aux::make_index_sequence<regions>{});
1365 #else
1366  return process_event_noexcept<get_event_mapping_t<get_mapped_t<TEvent>, mappings>>(event, deps, subs, has_exceptions{});
1367 #endif
1368  }
1369  template <class TEvent, class TDeps, class TSubs, class... Ts,
1370  __BOOST_SML_REQUIRES(!aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value &&
1371  !aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1372  bool process_internal_event(const TEvent &, TDeps &, TSubs &, Ts &&...) {
1373  return false;
1374  }
1375  template <class TEvent, class TDeps, class TSubs,
1376  __BOOST_SML_REQUIRES(!aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value)>
1377  bool process_internal_generic_event(const TEvent &, TDeps &, TSubs &, state_t &) {
1378  return false;
1379  }
1380  template <class TEvent, class TDeps, class TSubs,
1381  __BOOST_SML_REQUIRES(aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value)>
1382  bool process_internal_generic_event(const TEvent &event, TDeps &deps, TSubs &subs, state_t &current_state) {
1383  policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1384 #if BOOST_SML_DISABLE_EXCEPTIONS
1385  return process_event_impl<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(event, deps, subs, states_t{},
1386  current_state);
1387 #else
1388  return process_event_noexcept<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(event, deps, subs, current_state,
1389  has_exceptions{});
1390 #endif
1391  }
1392  template <class TEvent, class TDeps, class TSubs,
1393  __BOOST_SML_REQUIRES(aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value &&
1394  !aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1395  bool process_internal_event(const TEvent &event, TDeps &deps, TSubs &subs, state_t &current_state) {
1396  return process_internal_generic_event(event, deps, subs, current_state);
1397  }
1398  template <class TEvent, class TDeps, class TSubs,
1399  __BOOST_SML_REQUIRES(aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1400  bool process_internal_event(const TEvent &event, TDeps &deps, TSubs &subs, state_t &current_state) {
1401  policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1402 #if BOOST_SML_DISABLE_EXCEPTIONS
1403  return process_event_impl<get_event_mapping_t<get_mapped_t<TEvent>, mappings>>(event, deps, subs, states_t{}, current_state)
1404 #else
1405  return process_event_noexcept<get_event_mapping_t<get_mapped_t<TEvent>, mappings>>(event, deps, subs, current_state,
1406  has_exceptions{})
1407 #endif
1408  || process_internal_generic_event(event, deps, subs, current_state);
1409  }
1410  template <class TMappings, class TEvent, class TDeps, class TSubs, class... TStates>
1411  bool process_event_impl(const TEvent &event, TDeps &deps, TSubs &subs, const aux::type_list<TStates...> &states,
1412  aux::index_sequence<0>) {
1413  const auto lock = thread_safety_.create_lock();
1414  (void)lock;
1415  return dispatch_t::template dispatch<0, TMappings>(*this, current_state_[0], event, deps, subs, states);
1416  }
1417  template <class TMappings, class TEvent, class TDeps, class TSubs, class... TStates, int... Ns>
1418  bool process_event_impl(const TEvent &event, TDeps &deps, TSubs &subs, const aux::type_list<TStates...> &states,
1419  aux::index_sequence<Ns...>) {
1420  const auto lock = thread_safety_.create_lock();
1421  (void)lock;
1422 #if defined(__cpp_fold_expressions)
1423  return ((dispatch_t::template dispatch<0, TMappings>(*this, current_state_[Ns], event, deps, subs, states)), ...);
1424 #else
1425  auto handled = false;
1426  (void)aux::swallow{
1427  0,
1428  (handled |= dispatch_t::template dispatch<0, TMappings>(*this, current_state_[Ns], event, deps, subs, states), 0)...};
1429  return handled;
1430 #endif
1431  }
1432  template <class TMappings, class TEvent, class TDeps, class TSubs, class... TStates>
1433  bool process_event_impl(const TEvent &event, TDeps &deps, TSubs &subs, const aux::type_list<TStates...> &states,
1434  state_t &current_state) {
1435  const auto lock = thread_safety_.create_lock();
1436  (void)lock;
1437  return dispatch_t::template dispatch<0, TMappings>(*this, current_state, event, deps, subs, states);
1438  }
1439 #if !BOOST_SML_DISABLE_EXCEPTIONS
1440  template <class TMappings, class TEvent, class TDeps, class TSubs>
1441  bool process_event_noexcept(const TEvent &event, TDeps &deps, TSubs &subs, aux::false_type) noexcept {
1442  return process_event_impl<TMappings>(event, deps, subs, states_t{}, aux::make_index_sequence<regions>{});
1443  }
1444  template <class TMappings, class TEvent, class TDeps, class TSubs>
1445  bool process_event_noexcept(const TEvent &event, TDeps &deps, TSubs &subs, state_t &current_state, aux::false_type) noexcept {
1446  return process_event_impl<TMappings>(event, deps, subs, states_t{}, current_state);
1447  }
1448  template <class TMappings, class TEvent, class TDeps, class TSubs>
1449  bool process_event_noexcept(const TEvent &event, TDeps &deps, TSubs &subs, state_t &current_state, aux::true_type) noexcept {
1450  try {
1451  return process_event_impl<TMappings>(event, deps, subs, states_t{}, current_state);
1452  } catch (...) {
1453  return process_exception(deps, subs, exceptions{});
1454  }
1455  }
1456  template <class TMappings, class TEvent, class TDeps, class TSubs>
1457  bool process_event_noexcept(const TEvent &event, TDeps &deps, TSubs &subs, aux::true_type) {
1458  try {
1459  return process_event_impl<TMappings>(event, deps, subs, states_t{}, aux::make_index_sequence<regions>{});
1460  } catch (...) {
1461  return process_exception(deps, subs, exceptions{});
1462  }
1463  }
1464  template <class TDeps, class TSubs>
1465  bool process_exception(TDeps &deps, TSubs &subs, const aux::type_list<> &) {
1466  return process_internal_events(exception<_>{}, deps, subs);
1467  }
1468  template <class TDeps, class TSubs, class E, class... Es>
1469  bool process_exception(TDeps &deps, TSubs &subs, const aux::type_list<E, Es...> &) {
1470  try {
1471  throw;
1472  } catch (const typename E::type &e) {
1473  return process_internal_events(E{e}, deps, subs);
1474  } catch (...) {
1475  return process_exception(deps, subs, aux::type_list<Es...>{});
1476  }
1477  }
1478 #endif
1479  template <class TDeps, class TSubs, class... TEvents>
1480  bool process_defer_events(TDeps &, TSubs &, const bool, const aux::type<no_policy> &, const aux::type_list<TEvents...> &) {
1481  return false;
1482  }
1483  template <class TDeps, class TSubs, class TEvent>
1484  bool process_event_no_defer(TDeps &deps, TSubs &subs, const void *data) {
1485  const auto &event = *static_cast<const TEvent *>(data);
1486  policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1487 #if BOOST_SML_DISABLE_EXCEPTIONS
1488  const auto handled = process_event_impl<get_event_mapping_t<TEvent, mappings>>(event, deps, subs, states_t{},
1489  aux::make_index_sequence<regions>{});
1490 #else
1491  const auto handled = process_event_noexcept<get_event_mapping_t<TEvent, mappings>>(event, deps, subs, has_exceptions{});
1492 #endif
1493  if (handled && defer_again_) {
1494  ++defer_it_;
1495  } else {
1496  defer_.erase(defer_it_);
1497  defer_it_ = defer_.begin();
1498  defer_end_ = defer_.end();
1499  }
1500  return handled;
1501  }
1502  template <class TDeps, class TSubs, class TDeferQueue, class... TEvents>
1503  bool process_defer_events(TDeps &deps, TSubs &subs, const bool handled, const aux::type<TDeferQueue> &,
1504  const aux::type_list<TEvents...> &) {
1505  bool processed_events = false;
1506  if (handled) {
1507  using dispatch_table_t = bool (sm_impl::*)(TDeps &, TSubs &, const void *);
1508  const static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(sizeof...(TEvents))] = {
1509  &sm_impl::process_event_no_defer<TDeps, TSubs, TEvents>...};
1510  defer_processing_ = true;
1511  defer_again_ = false;
1512  defer_it_ = defer_.begin();
1513  defer_end_ = defer_.end();
1514  processed_events = defer_it_ != defer_end_;
1515  while (defer_it_ != defer_end_) {
1516  (this->*dispatch_table[defer_it_->id])(deps, subs, defer_it_->data);
1517  defer_again_ = false;
1518  }
1519  defer_processing_ = false;
1520  }
1521  return processed_events;
1522  }
1523  template <class TDeps, class TSubs, class... TEvents>
1524  bool process_queued_events(TDeps &, TSubs &, const aux::type<no_policy> &, const aux::type_list<TEvents...> &) {
1525  return false;
1526  }
1527  template <class TDeps, class TSubs, class TEvent>
1528  bool process_event_no_queue(TDeps &deps, TSubs &subs, const void *data) {
1529  const auto &event = *static_cast<const TEvent *>(data);
1530  policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1531 #if BOOST_SML_DISABLE_EXCEPTIONS
1532  return process_event_impl<get_event_mapping_t<TEvent, mappings>>(event, deps, subs, states_t{},
1533  aux::make_index_sequence<regions>{});
1534 #else
1535  return process_event_noexcept<get_event_mapping_t<TEvent, mappings>>(event, deps, subs, has_exceptions{});
1536 #endif
1537  }
1538  template <class TDeps, class TSubs, class TDeferQueue, class... TEvents>
1539  bool process_queued_events(TDeps &deps, TSubs &subs, const aux::type<TDeferQueue> &, const aux::type_list<TEvents...> &) {
1540  using dispatch_table_t = bool (sm_impl::*)(TDeps &, TSubs &, const void *);
1541  const static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(sizeof...(TEvents))] = {
1542  &sm_impl::process_event_no_queue<TDeps, TSubs, TEvents>...};
1543  bool wasnt_empty = !process_.empty();
1544  while (!process_.empty()) {
1545  (this->*dispatch_table[process_.front().id])(deps, subs, process_.front().data);
1546  process_.pop();
1547  }
1548  return wasnt_empty;
1549  }
1550  template <class TVisitor, class... TStates>
1551  void visit_current_states(const TVisitor &visitor, const aux::type_list<TStates...> &, aux::index_sequence<0>) const {
1552  using dispatch_table_t = void (*)(const TVisitor &);
1553  const static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(sizeof...(TStates))] = {
1554  &sm_impl::visit_state<TVisitor, TStates>...};
1555  dispatch_table[current_state_[0]](visitor);
1556  }
1557  template <class TVisitor, class... TStates, int... Ns>
1558  void visit_current_states(const TVisitor &visitor, const aux::type_list<TStates...> &, aux::index_sequence<Ns...>) const {
1559  using dispatch_table_t = void (*)(const TVisitor &);
1560  const static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(sizeof...(TStates))] = {
1561  &sm_impl::visit_state<TVisitor, TStates>...};
1562 #if defined(__cpp_fold_expressions)
1563  (dispatch_table[current_state_[Ns]](visitor), ...);
1564 #else
1565  (void)aux::swallow{0, (dispatch_table[current_state_[Ns]](visitor), 0)...};
1566 #endif
1567  }
1568  template <class TVisitor, class TState>
1569  static void visit_state(const TVisitor &visitor) {
1570  visitor(aux::string<TState>{});
1571  }
1572  bool is_terminated() const { return is_terminated_impl(aux::make_index_sequence<regions>{}); }
1573  bool is_terminated_impl(aux::index_sequence<0>) const {
1574  return current_state_[0] == aux::get_id<state_t, terminate_state>((states_ids_t *)0);
1575  }
1576  template <int... Ns>
1577  bool is_terminated_impl(aux::index_sequence<Ns...>) const {
1578 #if defined(__cpp_fold_expressions)
1579  return ((current_state_[Ns] == aux::get_id<state_t, terminate_state>((states_ids_t *)0)) && ...);
1580 #else
1581  auto result = true;
1582  (void)aux::swallow{
1583  0, (current_state_[Ns] == aux::get_id<state_t, terminate_state>((states_ids_t *)0) ? result : (result = false))...};
1584  return result;
1585 #endif
1586  }
1587  transitions_t transitions_;
1588  state_t current_state_[regions];
1589  thread_safety_t thread_safety_;
1590  defer_t defer_;
1591  process_t process_;
1592  defer_flag_t defer_processing_ = defer_flag_t{};
1593  defer_flag_t defer_again_ = defer_flag_t{};
1594  typename defer_t::const_iterator defer_it_;
1595  typename defer_t::const_iterator defer_end_;
1596 };
1597 template <class TSM>
1598 class sm {
1599  using sm_t = typename TSM::sm;
1600  using logger_t = typename TSM::logger_policy::type;
1601  using logger_dep_t =
1602  aux::conditional_t<aux::is_same<no_policy, logger_t>::value, aux::type_list<>, aux::type_list<logger_t &>>;
1603  using transitions_t = decltype(aux::declval<sm_t>().operator()());
1604  static_assert(concepts::composable<sm_t>::value, "Composable constraint is not satisfied!");
1605 
1606  public:
1607  using states = aux::apply_t<aux::unique_t, aux::apply_t<get_states, transitions_t>>;
1608  using state_machines = aux::apply_t<get_sub_sms, states>;
1609  using events = aux::apply_t<aux::unique_t, aux::apply_t<get_all_events, transitions_t>>;
1610  using transitions = aux::apply_t<aux::type_list, transitions_t>;
1611 
1612  private:
1613  using sm_all_t = aux::apply_t<get_non_empty_t, aux::join_t<aux::type_list<sm_t>, aux::apply_t<get_sm_t, state_machines>>>;
1614  using sub_sms_t =
1615  aux::apply_t<aux::pool,
1616  typename convert_to_sm<TSM, aux::apply_t<aux::unique_t, aux::apply_t<get_sub_sms, states>>>::type>;
1617  using deps = aux::apply_t<merge_deps, transitions_t>;
1618  using deps_t =
1619  aux::apply_t<aux::pool,
1620  aux::apply_t<aux::unique_t, aux::join_t<deps, sm_all_t, logger_dep_t, aux::apply_t<merge_deps, sub_sms_t>>>>;
1621  struct events_ids : aux::apply_t<aux::inherit, events> {};
1622 
1623  public:
1624  sm() : deps_{aux::init{}, aux::pool<>{}}, sub_sms_{aux::pool<>{}} { aux::get<sm_impl<TSM>>(sub_sms_).start(deps_, sub_sms_); }
1625  template <class TDeps, __BOOST_SML_REQUIRES(!aux::is_same<aux::remove_reference_t<TDeps>, sm>::value)>
1626  explicit sm(TDeps &&deps) : deps_{aux::init{}, aux::pool<TDeps>{deps}}, sub_sms_{aux::pool<TDeps>{deps}} {
1627  aux::get<sm_impl<TSM>>(sub_sms_).start(deps_, sub_sms_);
1628  }
1629  template <class... TDeps, __BOOST_SML_REQUIRES((sizeof...(TDeps) > 1) && aux::is_unique_t<TDeps...>::value)>
1630  explicit sm(TDeps &&... deps) : deps_{aux::init{}, aux::pool<TDeps...>{deps...}}, sub_sms_{aux::pool<TDeps...>{deps...}} {
1631  aux::get<sm_impl<TSM>>(sub_sms_).start(deps_, sub_sms_);
1632  }
1633  sm(aux::init, deps_t &deps) : deps_{deps}, sub_sms_{deps} { aux::get<sm_impl<TSM>>(sub_sms_).start(deps_, sub_sms_); }
1634  sm(const sm &) = default;
1635  sm(sm &&) = default;
1636  sm &operator=(const sm &) = default;
1637  sm &operator=(sm &&) = default;
1638  template <class TEvent, __BOOST_SML_REQUIRES(aux::is_base_of<TEvent, events_ids>::value)>
1639  bool process_event(const TEvent &event) {
1640  return aux::get<sm_impl<TSM>>(sub_sms_).process_event(event, deps_, sub_sms_);
1641  }
1642  template <class TEvent, __BOOST_SML_REQUIRES(!aux::is_base_of<TEvent, events_ids>::value)>
1643  bool process_event(const TEvent &event) {
1644  return aux::get<sm_impl<TSM>>(sub_sms_).process_event(unexpected_event<_, TEvent>{event}, deps_, sub_sms_);
1645  }
1646  template <class T = aux::identity<sm_t>, class TVisitor, __BOOST_SML_REQUIRES(concepts::callable<void, TVisitor>::value)>
1647  void visit_current_states(const TVisitor &visitor) const {
1648  using type = typename T::type;
1649  using sm_impl_t = sm_impl<typename TSM::template rebind<type>>;
1650  using states_t = typename sm_impl_t::states_t;
1651  constexpr auto regions = sm_impl_t::regions;
1652  aux::cget<sm_impl_t>(sub_sms_).visit_current_states(visitor, states_t{}, aux::make_index_sequence<regions>{});
1653  }
1654  template <class T = aux::identity<sm_t>, class TState>
1655  bool is(const TState &) const {
1656  using type = typename T::type;
1657  using sm_impl_t = sm_impl<typename TSM::template rebind<type>>;
1658  using state_t = typename sm_impl_t::state_t;
1659  using states_ids_t = typename sm_impl_t::states_ids_t;
1660  return aux::get_id<state_t, typename TState::type>((states_ids_t *)0) == aux::cget<sm_impl_t>(sub_sms_).current_state_[0];
1661  }
1662  template <class T = aux::identity<sm_t>, template <class...> class TState>
1663  bool is(const TState<terminate_state> &) const {
1664  using type = typename T::type;
1665  using sm_impl_t = sm_impl<typename TSM::template rebind<type>>;
1666  using state_t = typename sm_impl_t::state_t;
1667  using states_ids_t = typename sm_impl_t::states_ids_t;
1668  auto result = false;
1669  visit_current_states<T>([&](auto state) {
1670  (void)state;
1671  result |= (aux::get_id<state_t, terminate_state>((states_ids_t *)0) ==
1672  aux::get_id<state_t, typename decltype(state)::type>((states_ids_t *)0));
1673  });
1674  return result;
1675  }
1676  template <class T = aux::identity<sm_t>, class... TStates,
1677  __BOOST_SML_REQUIRES(sizeof...(TStates) == sm_impl<typename TSM::template rebind<typename T::type>>::regions)>
1678  bool is(const TStates &...) const {
1679  using type = typename T::type;
1680  using sm_impl_t = sm_impl<typename TSM::template rebind<type>>;
1681  using states_ids_t = typename sm_impl_t::states_ids_t;
1682  using state_t = typename sm_impl_t::state_t;
1683  auto result = true;
1684  auto i = 0;
1685  state_t state_ids[] = {aux::get_id<state_t, typename TStates::type>((states_ids_t *)0)...};
1686  visit_current_states<T>([&](auto state) {
1687  (void)state;
1688  result &= (aux::get_id<state_t, typename decltype(state)::type>((states_ids_t *)0) == state_ids[i++]);
1689  });
1690  return result;
1691  }
1692  template <class T = aux::identity<sm_t>, class... TStates,
1693  __BOOST_SML_REQUIRES(!aux::is_same<no_policy, typename TSM::testing_policy>::value && aux::always<T>::value)>
1694  void set_current_states(const TStates &...) {
1695  using type = typename T::type;
1696  using sm_impl_t = sm_impl<typename TSM::template rebind<type>>;
1697  using states_ids_t = typename sm_impl_t::states_ids_t;
1698  using state_t = typename sm_impl_t::state_t;
1699  auto &sm = aux::get<sm_impl_t>(sub_sms_);
1700  auto region = 0;
1701 #if defined(__cpp_fold_expressions)
1702  ((sm.current_state_[region++] = aux::get_id<state_t, typename TStates::type>((states_ids_t *)0)), ...);
1703 #else
1704  (void)aux::swallow{0,
1705  (sm.current_state_[region++] = aux::get_id<state_t, typename TStates::type>((states_ids_t *)0), 0)...};
1706 #endif
1707  }
1708  template <class T>
1709  operator T &() {
1710  return aux::get<sm_impl<typename TSM::template rebind<T>>>(sub_sms_);
1711  }
1712  template <class T>
1713  operator const T &() {
1714  return aux::cget<sm_impl<typename TSM::template rebind<T>>>(sub_sms_);
1715  }
1716 
1717  private:
1718  deps_t deps_;
1719  sub_sms_t sub_sms_;
1720 };
1721 }
1722 namespace front {
1723 struct operator_base {};
1724 struct action_base {};
1725 template <class TRootSM, class... TSubSMs>
1726 TRootSM get_root_sm_impl(aux::pool<TRootSM, TSubSMs...> *);
1727 template <class TSubs>
1728 using get_root_sm_t = decltype(get_root_sm_impl((TSubs *)0));
1729 template <class, class>
1730 aux::type_list<action_base> args1__(...);
1731 template <class T, class E>
1732 auto args1__(int) -> aux::function_traits_t<decltype(&T::operator())>;
1733 template <class T, class E>
1734 auto args__(int) -> aux::function_traits_t<decltype(&T::__BOOST_SML_TEMPLATE_KEYWORD operator()<back::get_event_t<E>>)>;
1735 template <class T, class E>
1736 auto args__(...) -> decltype(args1__<T, E>(0));
1737 template <class T, class E>
1738 using args_t = decltype(args__<T, E>(0));
1739 template <class T, class TEvent, class TSM, class TDeps>
1740 decltype(auto) get_arg(const aux::type<T> &, const TEvent &, TSM &, TDeps &deps) {
1741  return aux::get<T>(deps);
1742 }
1743 template <class TEvent, class TSM, class TDeps>
1744 decltype(auto) get_arg(const aux::type<TEvent> &, const TEvent &event, TSM &, TDeps &) {
1745  return event;
1746 }
1747 template <class TEvent, class TSM, class TDeps>
1748 decltype(auto) get_arg(const aux::type<const TEvent &> &, const TEvent &event, TSM &, TDeps &) {
1749  return event;
1750 }
1751 template <class T, class TEvent, class TSM, class TDeps>
1752 decltype(auto) get_arg(const aux::type<const TEvent &> &, const back::unexpected_event<T, TEvent> &event, TSM &, TDeps &) {
1753  return event.event_;
1754 }
1755 template <class T, class TEvent, class TSM, class TDeps>
1756 decltype(auto) get_arg(const aux::type<const TEvent &> &, const back::on_entry<T, TEvent> &event, TSM &, TDeps &) {
1757  return event.event_;
1758 }
1759 template <class T, class TEvent, class TSM, class TDeps>
1760 decltype(auto) get_arg(const aux::type<const TEvent &> &, const back::on_exit<T, TEvent> &event, TSM &, TDeps &) {
1761  return event.event_;
1762 }
1763 template <class T, class TEvent, class TSM, class TDeps>
1764 decltype(auto) get_arg(const aux::type<const TEvent &> &, const back::exception<T, TEvent> &event, TSM &, TDeps &) {
1765  return event.exception_;
1766 }
1767 template <class... TEvents, class TEvent, class TSM, class TDeps>
1768 decltype(auto) get_arg(const aux::type<back::defer<TEvents...>> &, const TEvent, TSM &sm, TDeps &) {
1769  return back::defer<TEvents...>{sm.defer_};
1770 }
1771 template <class... TEvents, class TEvent, class TSM, class TDeps>
1772 decltype(auto) get_arg(const aux::type<back::process<TEvents...>> &, const TEvent, TSM &sm, TDeps &) {
1773  return back::process<TEvents...>{sm.process_};
1774 }
1775 template <class, class, class>
1776 struct call;
1777 template <class TEvent>
1778 struct call<TEvent, aux::type_list<>, back::no_policy> {
1779  template <class T, class TSM, class TDeps, class TSubs>
1780  static auto execute(T object, const TEvent &, TSM &, TDeps &, TSubs &) {
1781  return object();
1782  }
1783 };
1784 template <class TEvent, class TLogger>
1785 struct call<TEvent, aux::type_list<>, TLogger> {
1786  template <class T, class TSM, class TDeps, class TSubs>
1787  static auto execute(T object, const TEvent &event, TSM &, TDeps &deps, TSubs &) {
1788  using result_type = decltype(object());
1789  return execute_impl<typename TSM::sm_t>(aux::type<result_type>{}, object, event, deps);
1790  }
1791  template <class TSM, class T, class TDeps>
1792  static auto execute_impl(const aux::type<bool> &, T object, const TEvent &event, TDeps &deps) {
1793  const auto result = object();
1794  back::policies::log_guard<TSM>(aux::type<TLogger>{}, deps, object, event, result);
1795  return result;
1796  }
1797  template <class TSM, class T, class TDeps>
1798  static auto execute_impl(const aux::type<void> &, T object, const TEvent &event, TDeps &deps) {
1799  back::policies::log_action<TSM>(aux::type<TLogger>{}, deps, object, event);
1800  object();
1801  }
1802 };
1803 template <class TEvent>
1804 struct call<TEvent, aux::type_list<TEvent>, back::no_policy> {
1805  template <class T, class TSM, class TDeps, class TSubs>
1806  static auto execute(T object, const TEvent &event, TSM &, TDeps &, TSubs &) {
1807  return object(event);
1808  }
1809 };
1810 template <class TEvent, class TLogger>
1811 struct call<TEvent, aux::type_list<TEvent>, TLogger> {
1812  template <class T, class TSM, class TDeps, class TSubs>
1813  static auto execute(T object, const TEvent &event, TSM &, TDeps &deps, TSubs &) {
1814  using result_type = decltype(object(event));
1815  return execute_impl<typename TSM::sm_t>(aux::type<result_type>{}, object, event, deps);
1816  }
1817  template <class TSM, class T, class TDeps>
1818  static auto execute_impl(const aux::type<bool> &, T object, const TEvent &event, TDeps &deps) {
1819  const auto result = object(event);
1820  back::policies::log_guard<TSM>(aux::type<TLogger>{}, deps, object, event, result);
1821  return result;
1822  }
1823  template <class TSM, class T, class TDeps>
1824  static auto execute_impl(const aux::type<void> &, T object, const TEvent &event, TDeps &deps) {
1825  back::policies::log_action<TSM>(aux::type<TLogger>{}, deps, object, event);
1826  object(event);
1827  }
1828 };
1829 template <class TEvent>
1830 struct call<TEvent, aux::type_list<action_base>, back::no_policy> {
1831  template <class T, class TSM, class TDeps, class TSubs>
1832  static auto execute(T object, const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1833  return object(event, sm, deps, subs);
1834  }
1835 };
1836 template <class TEvent, class TLogger>
1837 struct call<TEvent, aux::type_list<action_base>, TLogger> {
1838  template <class T, class TSM, class TDeps, class TSubs>
1839  static auto execute(T object, const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1840  return object(event, sm, deps, subs);
1841  }
1842 };
1843 template <class TEvent, class... Ts>
1844 struct call<TEvent, aux::type_list<Ts...>, back::no_policy> {
1845  template <class T, class TSM, class TDeps, class TSubs>
1846  static auto execute(T object, const TEvent &event, TSM &sm, TDeps &deps, TSubs &) {
1847  return object(get_arg(aux::type<Ts>{}, event, sm, deps)...);
1848  }
1849 };
1850 template <class TEvent, class... Ts, class TLogger>
1851 struct call<TEvent, aux::type_list<Ts...>, TLogger> {
1852  template <class T, class TSM, class TDeps, class TSubs>
1853  static auto execute(T object, const TEvent &event, TSM &sm, TDeps &deps, TSubs &) {
1854  using result_type = decltype(object(get_arg(aux::type<Ts>{}, event, sm, deps)...));
1855  return execute_impl<typename TSM::sm_t>(aux::type<result_type>{}, object, event, sm, deps);
1856  }
1857  template <class TSM, class T, class SM, class TDeps>
1858  static auto execute_impl(const aux::type<bool> &, T object, const TEvent &event, SM &sm, TDeps &deps) {
1859  const auto result = object(get_arg(aux::type<Ts>{}, event, sm, deps)...);
1860  back::policies::log_guard<TSM>(aux::type<TLogger>{}, deps, object, event, result);
1861  return result;
1862  }
1863  template <class TSM, class T, class SM, class TDeps>
1864  static auto execute_impl(const aux::type<void> &, T object, const TEvent &event, SM &sm, TDeps &deps) {
1865  back::policies::log_action<TSM>(aux::type<TLogger>{}, deps, object, event);
1866  object(get_arg(aux::type<Ts>{}, event, sm, deps)...);
1867  }
1868 };
1869 template <class... Ts>
1870 class seq_ : operator_base {
1871  public:
1872  explicit seq_(Ts... ts) : a(ts...) {}
1873  template <class TEvent, class TSM, class TDeps, class TSubs>
1874  void operator()(const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1875  for_all(aux::make_index_sequence<sizeof...(Ts)>{}, event, sm, deps, subs);
1876  }
1877 
1878  private:
1879  template <int... Ns, class TEvent, class TSM, class TDeps, class TSubs>
1880  void for_all(const aux::index_sequence<Ns...> &, const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1881 #if defined(__cpp_fold_expressions)
1882  (call<TEvent, args_t<Ts, TEvent>, typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&a), event, sm, deps, subs), ...);
1883 #else
1884  (void)aux::swallow{
1885  0, (call<TEvent, args_t<Ts, TEvent>, typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&a), event, sm, deps, subs),
1886  0)...};
1887 #endif
1888  }
1889  aux::tuple<Ts...> a;
1890 };
1891 template <class... Ts>
1892 class and_ : operator_base {
1893  public:
1894  explicit and_(Ts... ts) : g(ts...) {}
1895  template <class TEvent, class TSM, class TDeps, class TSubs>
1896  auto operator()(const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1897  return for_all(aux::make_index_sequence<sizeof...(Ts)>{}, event, sm, deps, subs);
1898  }
1899 
1900  private:
1901  template <int... Ns, class TEvent, class TSM, class TDeps, class TSubs>
1902  auto for_all(const aux::index_sequence<Ns...> &, const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1903 #if defined(__cpp_fold_expressions)
1904  return (call<TEvent, args_t<Ts, TEvent>, typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&g), event, sm, deps, subs) &&
1905  ...);
1906 #else
1907  auto result = true;
1908  (void)aux::swallow{0, (result && call<TEvent, args_t<Ts, TEvent>, typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&g),
1909  event, sm, deps, subs)
1910  ? result
1911  : (result = false))...};
1912  return result;
1913 #endif
1914  }
1915  aux::tuple<Ts...> g;
1916 };
1917 template <class... Ts>
1918 class or_ : operator_base {
1919  public:
1920  explicit or_(Ts... ts) : g(ts...) {}
1921  template <class TEvent, class TSM, class TDeps, class TSubs>
1922  auto operator()(const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1923  return for_all(aux::make_index_sequence<sizeof...(Ts)>{}, event, sm, deps, subs);
1924  }
1925 
1926  private:
1927  template <int... Ns, class TEvent, class TSM, class TDeps, class TSubs>
1928  auto for_all(const aux::index_sequence<Ns...> &, const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1929 #if defined(__cpp_fold_expressions)
1930  return (call<TEvent, args_t<Ts, TEvent>, typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&g), event, sm, deps, subs) ||
1931  ...);
1932 #else
1933  auto result = false;
1934  (void)aux::swallow{0, (result || call<TEvent, args_t<Ts, TEvent>, typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&g),
1935  event, sm, deps, subs)
1936  ? (result = true)
1937  : result)...};
1938  return result;
1939 #endif
1940  }
1941  aux::tuple<Ts...> g;
1942 };
1943 template <class T>
1944 class not_ : operator_base {
1945  public:
1946  explicit not_(T t) : g(t) {}
1947  template <class TEvent, class TSM, class TDeps, class TSubs>
1948  auto operator()(const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1949  return !call<TEvent, args_t<T, TEvent>, typename TSM::logger_t>::execute(g, event, sm, deps, subs);
1950  }
1951 
1952  private:
1953  T g;
1954 };
1955 }
1956 template <class T, __BOOST_SML_REQUIRES(concepts::callable<bool, T>::value)>
1957 auto operator!(const T &t) {
1958  return front::not_<aux::zero_wrapper<T>>(aux::zero_wrapper<T>{t});
1959 }
1960 template <class T1, class T2, __BOOST_SML_REQUIRES(concepts::callable<bool, T1>::value &&concepts::callable<bool, T2>::value)>
1961 auto operator&&(const T1 &t1, const T2 &t2) {
1962  return front::and_<aux::zero_wrapper<T1>, aux::zero_wrapper<T2>>(aux::zero_wrapper<T1>{t1}, aux::zero_wrapper<T2>{t2});
1963 }
1964 template <class T1, class T2, __BOOST_SML_REQUIRES(concepts::callable<bool, T1>::value &&concepts::callable<bool, T2>::value)>
1965 auto operator||(const T1 &t1, const T2 &t2) {
1966  return front::or_<aux::zero_wrapper<T1>, aux::zero_wrapper<T2>>(aux::zero_wrapper<T1>{t1}, aux::zero_wrapper<T2>{t2});
1967 }
1968 template <class T1, class T2, __BOOST_SML_REQUIRES(concepts::callable<void, T1>::value &&concepts::callable<void, T2>::value)>
1969 auto operator,(const T1 &t1, const T2 &t2) {
1970  return front::seq_<aux::zero_wrapper<T1>, aux::zero_wrapper<T2>>(aux::zero_wrapper<T1>{t1}, aux::zero_wrapper<T2>{t2});
1971 }
1972 namespace front {
1973 namespace actions {
1974 struct defer : action_base {
1975  template <class TEvent, class TSM, class TDeps, class TSubs>
1976  void operator()(const TEvent &event, TSM &sm, TDeps &, TSubs &) {
1977  if (sm.defer_processing_) {
1978  sm.defer_again_ = true;
1979  } else {
1980  sm.defer_.push_back(event);
1981  }
1982  }
1983 };
1984 }
1985 }
1986 using testing = back::policies::testing;
1987 template <class T>
1988 using logger = back::policies::logger<T>;
1989 template <class T>
1990 using thread_safe = back::policies::thread_safe<T>;
1991 template <class T>
1992 using dispatch = back::policies::dispatch<T>;
1993 template <template <class...> class T>
1994 using defer_queue = back::policies::defer_queue<T>;
1995 template <template <class...> class T>
1996 using process_queue = back::policies::process_queue<T>;
1997 #if defined(COMPILING_WITH_MSVC)
1998 template <class T, class... TPolicies, class T__ = aux::remove_reference_t<decltype(aux::declval<T>())>>
1999 using sm = back::sm<back::sm_policy<T__, TPolicies...>>;
2000 #else
2001 template <class T, class... TPolicies>
2002 using sm = back::sm<back::sm_policy<T, TPolicies...>>;
2003 #endif
2004 namespace concepts {
2005 aux::false_type transitional_impl(...);
2006 template <class T>
2007 auto transitional_impl(T &&t) -> aux::always<typename T::dst_state, typename T::src_state, typename T::event, typename T::deps,
2008  decltype(T::initial), decltype(T::history)>;
2009 template <class T>
2010 struct transitional : decltype(transitional_impl(aux::declval<T>())) {};
2011 }
2012 namespace front {
2013 namespace actions {
2014 struct process {
2015  template <class TEvent>
2016  class process_impl : public action_base {
2017  public:
2018  explicit process_impl(const TEvent &event) : event(event) {}
2019  template <class T, class TSM, class TDeps, class TSubs>
2020  void operator()(const T &, TSM &, TDeps &, TSubs &subs) {
2021  aux::get<get_root_sm_t<TSubs>>(subs).process_.push(event);
2022  }
2023 
2024  private:
2025  TEvent event;
2026  };
2027  template <class TEvent>
2028  auto operator()(const TEvent &event) {
2029  return process_impl<TEvent>{event};
2030  }
2031 };
2032 }
2033 }
2034 namespace front {
2035 template <class, class>
2036 struct transition_eg;
2037 template <class, class>
2038 struct transition_ea;
2039 template <class TEvent>
2040 struct event {
2041  template <class T, __BOOST_SML_REQUIRES(concepts::callable<bool, T>::value)>
2042  auto operator[](const T &t) const {
2043  return transition_eg<event, aux::zero_wrapper<T>>{*this, aux::zero_wrapper<T>{t}};
2044  }
2045  template <class T, __BOOST_SML_REQUIRES(concepts::callable<void, T>::value)>
2046  auto operator/(const T &t) const {
2047  return transition_ea<event, aux::zero_wrapper<T>>{*this, aux::zero_wrapper<T>{t}};
2048  }
2049  auto operator()() const { return TEvent{}; }
2050 };
2051 }
2052 namespace front {
2053 struct initial_state {};
2054 struct history_state {};
2055 template <class...>
2056 struct transition;
2057 template <class, class>
2058 struct transition_sa;
2059 template <class, class>
2060 struct transition_sg;
2061 template <class, class>
2062 struct transition_eg;
2063 template <class>
2064 struct state;
2065 template <class TState>
2066 struct state_impl {
2067  template <class T>
2068  auto operator<=(const T &t) const {
2069  return transition<TState, T>{static_cast<const TState &>(*this), t};
2070  }
2071  template <class T>
2072  auto operator+(const T &t) const {
2073  return transition<TState, T>{static_cast<const TState &>(*this), t};
2074  }
2075  template <class T, __BOOST_SML_REQUIRES(concepts::callable<bool, T>::value)>
2076  auto operator[](const T &t) const {
2077  return transition_sg<TState, aux::zero_wrapper<T>>{static_cast<const TState &>(*this), aux::zero_wrapper<T>{t}};
2078  }
2079  template <class T, __BOOST_SML_REQUIRES(concepts::callable<void, T>::value)>
2080  auto operator/(const T &t) const {
2081  return transition_sa<TState, aux::zero_wrapper<T>>{static_cast<const TState &>(*this), aux::zero_wrapper<T>{t}};
2082  }
2083 };
2084 template <class TState>
2085 struct state : state_impl<state<TState>> {
2086  using type = TState;
2087  static constexpr auto initial = false;
2088  static constexpr auto history = false;
2089  auto operator*() const { return state<TState(initial_state)>{}; }
2090  auto operator()(const initial_state &) const { return state<TState(initial_state)>{}; }
2091  auto operator()(const history_state &) const { return state<TState(history_state)>{}; }
2092  template <class... Ts>
2093  auto operator()(const state<Ts> &...) const {
2094  return state<TState(Ts...)>{};
2095  }
2096  template <class T>
2097  auto operator=(const T &t) const {
2098  return transition<T, state>{t, *this};
2099  }
2100  template <class T>
2101  auto sm() const {
2102  return state<back::sm<back::sm_policy<T, aux::identity<TState>>>>{};
2103  }
2104 };
2105 template <class TState>
2106 struct state<TState(initial_state)> : state_impl<state<TState(initial_state)>> {
2107  using type = TState;
2108  static constexpr auto initial = true;
2109  static constexpr auto history = false;
2110  template <class T>
2111  auto operator=(const T &t) const {
2112  return transition<T, state>{t, *this};
2113  }
2114 };
2115 template <class TState>
2116 struct state<TState(history_state)> : state_impl<state<TState(history_state)>> {
2117  using type = TState;
2118  static constexpr auto initial = true;
2119  static constexpr auto history = true;
2120  template <class T>
2121  auto operator=(const T &t) const {
2122  return transition<T, state>{t, *this};
2123  }
2124 };
2125 #if defined(COMPILING_WITH_MSVC)
2126 template <class T, class T__ = aux::remove_reference_t<decltype(aux::declval<T>())>, class = void>
2127 struct state_sm {
2128  using type = state<T>;
2129 };
2130 template <class T, class T__>
2131 struct state_sm<T, T__, aux::enable_if_t<concepts::composable<T__>::value>> {
2132  using type = state<back::sm<back::sm_policy<T__>>>;
2133 };
2134 #else
2135 template <class T, class = void>
2136 struct state_sm {
2137  using type = state<T>;
2138 };
2139 template <class T>
2140 struct state_sm<T, aux::enable_if_t<concepts::composable<T>::value>> {
2141  using type = state<back::sm<back::sm_policy<T>>>;
2142 };
2143 #endif
2144 }
2145 namespace front {
2146 struct internal {};
2147 template <class, class>
2148 struct ignore;
2149 template <class E, class... Ts>
2150 struct ignore<E, aux::type_list<Ts...>> {
2151  template <class T>
2152  struct non_events {
2153  using type =
2154  aux::conditional_t<aux::is_same<back::get_event_t<E>, aux::remove_const_t<aux::remove_reference_t<T>>>::value ||
2155  aux::is_same<T, action_base>::value,
2156  aux::type_list<>, aux::type_list<T>>;
2157  };
2158  using type = aux::join_t<typename non_events<Ts>::type...>;
2159 };
2160 template <class T, class E, class = void>
2161 struct get_deps {
2162  using type = typename ignore<E, args_t<T, E>>::type;
2163 };
2164 template <class T, class E>
2165 using get_deps_t = typename get_deps<T, E>::type;
2166 template <template <class...> class T, class... Ts, class E>
2167 struct get_deps<T<Ts...>, E, aux::enable_if_t<aux::is_base_of<operator_base, T<Ts...>>::value>> {
2168  using type = aux::join_t<get_deps_t<Ts, E>...>;
2169 };
2170 struct always {
2171  using type = always;
2172  bool operator()() const { return true; }
2173  __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
2174 };
2175 struct none {
2176  using type = none;
2177  void operator()() {}
2178  __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
2179 };
2180 template <class...>
2181 struct transition;
2182 template <class E, class G>
2183 struct transition<front::event<E>, G> {
2184  template <class T>
2185  auto operator/(const T &t) const {
2186  return transition<front::event<E>, G, aux::zero_wrapper<T>>{e, g, aux::zero_wrapper<T>{t}};
2187  }
2188  front::event<E> e;
2189  G g;
2190 };
2191 template <class E, class G, class A>
2192 struct transition<front::event<E>, G, A> {
2193  front::event<E> e;
2194  G g;
2195  A a;
2196 };
2197 template <class S2, class G, class A>
2198 struct transition<state<S2>, G, A> : transition<state<internal>, state<S2>, front::event<back::anonymous>, G, A> {
2199  using transition<state<internal>, state<S2>, front::event<back::anonymous>, G, A>::g;
2200  using transition<state<internal>, state<S2>, front::event<back::anonymous>, G, A>::a;
2201  transition(const G &g, const A &a) : transition<state<internal>, state<S2>, front::event<back::anonymous>, G, A>{g, a} {}
2202  template <class T>
2203  auto operator=(const T &) const {
2204  return transition<T, state<S2>, front::event<back::anonymous>, G, A>{g, a};
2205  }
2206 };
2207 template <class S1, class S2>
2208 struct transition<state<S1>, state<S2>> : transition<state<S1>, state<S2>, front::event<back::anonymous>, always, none> {
2209  transition(const state<S1> &, const state<S2> &)
2210  : transition<state<S1>, state<S2>, front::event<back::anonymous>, always, none>{always{}, none{}} {}
2211 };
2212 template <class S2, class G>
2213 struct transition_sg<state<S2>, G> : transition<state<internal>, state<S2>, front::event<back::anonymous>, G, none> {
2214  using transition<state<internal>, state<S2>, front::event<back::anonymous>, G, none>::g;
2215  transition_sg(const state<S2> &, const G &g)
2216  : transition<state<internal>, state<S2>, front::event<back::anonymous>, G, none>{g, none{}} {}
2217  template <class T>
2218  auto operator/(const T &t) const {
2219  return transition<state<S2>, G, aux::zero_wrapper<T>>{g, aux::zero_wrapper<T>{t}};
2220  }
2221  template <class T>
2222  auto operator=(const T &) const {
2223  return transition<T, state<S2>, front::event<back::anonymous>, G, none>{g, none{}};
2224  }
2225 };
2226 template <class S2, class A>
2227 struct transition_sa<state<S2>, A> : transition<state<internal>, state<S2>, front::event<back::anonymous>, always, A> {
2228  using transition<state<internal>, state<S2>, front::event<back::anonymous>, always, A>::a;
2229  transition_sa(const state<S2> &, const A &a)
2230  : transition<state<internal>, state<S2>, front::event<back::anonymous>, always, A>{always{}, a} {}
2231  template <class T>
2232  auto operator=(const T &) const {
2233  return transition<T, state<S2>, front::event<back::anonymous>, always, A>{always{}, a};
2234  }
2235 };
2236 template <class S2, class E>
2237 struct transition<state<S2>, front::event<E>> {
2238  template <class T>
2239  auto operator=(const T &) const {
2240  return transition<T, state<S2>, front::event<E>, always, none>{always{}, none{}};
2241  }
2242  const state<S2> &s2;
2243  front::event<E> e;
2244 };
2245 template <class E, class G>
2246 struct transition_eg<front::event<E>, G> {
2247  template <class T>
2248  auto operator/(const T &t) const {
2249  return transition<front::event<E>, G, aux::zero_wrapper<T>>{e, g, aux::zero_wrapper<T>{t}};
2250  }
2251  front::event<E> e;
2252  G g;
2253 };
2254 template <class E, class A>
2255 struct transition_ea<front::event<E>, A> {
2256  front::event<E> e;
2257  A a;
2258 };
2259 template <class S1, class S2, class G, class A>
2260 struct transition<state<S1>, transition<state<S2>, G, A>>
2261  : transition<state<S1>, state<S2>, front::event<back::anonymous>, G, A> {
2262  transition(const state<S1> &, const transition<state<S2>, G, A> &t)
2263  : transition<state<S1>, state<S2>, front::event<back::anonymous>, G, A>{t.g, t.a} {}
2264 };
2265 template <class S1, class E, class G, class A>
2266 struct transition<state<S1>, transition<front::event<E>, G, A>>
2267  : transition<state<internal>, state<S1>, front::event<E>, G, A> {
2268  using transition<state<internal>, state<S1>, front::event<E>, G, A>::g;
2269  using transition<state<internal>, state<S1>, front::event<E>, G, A>::a;
2270  transition(const state<S1> &, const transition<front::event<E>, G, A> &t)
2271  : transition<state<internal>, state<S1>, front::event<E>, G, A>{t.g, t.a} {}
2272  template <class T>
2273  auto operator=(const T &) const {
2274  return transition<T, state<S1>, front::event<E>, G, A>{g, a};
2275  }
2276 };
2277 template <class S1, class S2, class E>
2278 struct transition<state<S1>, transition<state<S2>, front::event<E>>>
2279  : transition<state<S1>, state<S2>, front::event<E>, always, none> {
2280  transition(const state<S1> &, const transition<state<S2>, front::event<E>> &)
2281  : transition<state<S1>, state<S2>, front::event<E>, always, none>{always{}, none{}} {}
2282 };
2283 template <class S1, class S2, class G>
2284 struct transition<state<S1>, transition_sg<state<S2>, G>>
2285  : transition<state<S1>, state<S2>, front::event<back::anonymous>, G, none> {
2286  transition(const state<S1> &, const transition_sg<state<S2>, G> &t)
2287  : transition<state<S1>, state<S2>, front::event<back::anonymous>, G, none>{t.g, none{}} {}
2288 };
2289 template <class S1, class S2, class A>
2290 struct transition<state<S1>, transition_sa<state<S2>, A>>
2291  : transition<state<S1>, state<S2>, front::event<back::anonymous>, always, A> {
2292  transition(const state<S1> &, const transition_sa<state<S2>, A> &t)
2293  : transition<state<S1>, state<S2>, front::event<back::anonymous>, always, A>{always{}, t.a} {}
2294 };
2295 template <class S2, class E, class G>
2296 struct transition<state<S2>, transition_eg<front::event<E>, G>>
2297  : transition<state<internal>, state<S2>, front::event<E>, G, none> {
2298  using transition<state<internal>, state<S2>, front::event<E>, G, none>::g;
2299  transition(const state<S2> &, const transition_eg<front::event<E>, G> &t)
2300  : transition<state<internal>, state<S2>, front::event<E>, G, none>{t.g, none{}} {}
2301  template <class T>
2302  auto operator=(const T &) const {
2303  return transition<T, state<S2>, front::event<E>, G, none>{g, none{}};
2304  }
2305 };
2306 template <class S1, class S2, class E, class G>
2307 struct transition<state<S1>, transition<state<S2>, transition_eg<front::event<E>, G>>>
2308  : transition<state<S1>, state<S2>, front::event<E>, G, none> {
2309  transition(const state<S1> &, const transition<state<S2>, transition_eg<front::event<E>, G>> &t)
2310  : transition<state<S1>, state<S2>, front::event<E>, G, none>{t.g, none{}} {}
2311 };
2312 template <class S2, class E, class A>
2313 struct transition<state<S2>, transition_ea<front::event<E>, A>>
2314  : transition<state<internal>, state<S2>, front::event<E>, always, A> {
2315  using transition<state<internal>, state<S2>, front::event<E>, always, A>::a;
2316  transition(const state<S2> &, const transition_ea<front::event<E>, A> &t)
2317  : transition<state<internal>, state<S2>, front::event<E>, always, A>{always{}, t.a} {}
2318  template <class T>
2319  auto operator=(const T &) const {
2320  return transition<T, state<S2>, front::event<E>, always, A>{always{}, a};
2321  }
2322 };
2323 template <class S1, class S2, class E, class A>
2324 struct transition<state<S1>, transition<state<S2>, transition_ea<front::event<E>, A>>>
2325  : transition<state<S1>, state<S2>, front::event<E>, always, A> {
2326  transition(const state<S1> &, const transition<state<S2>, transition_ea<front::event<E>, A>> &t)
2327  : transition<state<S1>, state<S2>, front::event<E>, always, A>{always{}, t.a} {}
2328 };
2329 template <class S1, class S2, class E, class G, class A>
2330 struct transition<state<S1>, transition<state<S2>, transition<front::event<E>, G, A>>>
2331  : transition<state<S1>, state<S2>, front::event<E>, G, A> {
2332  transition(const state<S1> &, const transition<state<S2>, transition<front::event<E>, G, A>> &t)
2333  : transition<state<S1>, state<S2>, front::event<E>, G, A>{t.g, t.a} {}
2334 };
2335 template <class T, class TSubs, class... Ts, class... THs>
2336 void update_composite_states(TSubs &subs, aux::true_type, const aux::type_list<THs...> &) {
2337  using state_t = typename T::state_t;
2338  auto &sm = back::sub_sm<T>::get(&subs);
2339  (void)sm;
2340 #if defined(__cpp_fold_expressions)
2341  ((sm.current_state_[aux::get_id<state_t, THs>((typename T::initial_states_ids_t *)0)] =
2342  aux::get_id<state_t, THs>((typename T::states_ids_t *)0)),
2343  ...);
2344 #else
2345  (void)aux::swallow{0, (sm.current_state_[aux::get_id<state_t, THs>((typename T::initial_states_ids_t *)0)] =
2346  aux::get_id<state_t, THs>((typename T::states_ids_t *)0),
2347  0)...};
2348 #endif
2349 }
2350 template <class T, class TSubs, class... Ts>
2351 void update_composite_states(TSubs &subs, aux::false_type, Ts &&...) {
2352  back::sub_sm<T>::get(&subs).initialize(typename T::initial_states_t{});
2353 }
2354 template <class SM, class TDeps, class TSubs, class TSrcState, class TDstState>
2355 void update_current_state(SM &, TDeps &deps, TSubs &, typename SM::state_t &current_state,
2356  const typename SM::state_t &new_state, const TSrcState &, const TDstState &) {
2357  back::policies::log_state_change<typename SM::sm_t>(aux::type<typename SM::logger_t>{}, deps,
2358  aux::string<typename TSrcState::type>{},
2359  aux::string<typename TDstState::type>{});
2360  current_state = new_state;
2361 }
2362 template <class SM, class TDeps, class TSubs, class TSrcState, class T>
2363 void update_current_state(SM &, TDeps &deps, TSubs &subs, typename SM::state_t &current_state,
2364  const typename SM::state_t &new_state, const TSrcState &, const state<back::sm<T>> &) {
2365  back::policies::log_state_change<typename SM::sm_t>(aux::type<typename SM::logger_t>{}, deps,
2366  aux::string<typename TSrcState::type>{}, aux::string<T>{});
2367  current_state = new_state;
2368  update_composite_states<back::sm_impl<T>>(subs, typename back::sm_impl<T>::has_history_states{},
2369  typename back::sm_impl<T>::history_states_t{});
2370 }
2371 template <class TDeps, class TSubs, class TDstState>
2372 void process_internal_transitions(TDeps &, TSubs &, const TDstState &) {}
2373 template <class TDeps, class TSubs, class T>
2374 void process_internal_transitions(TDeps &deps, TSubs &subs, const state<back::sm<T>> &) {
2375  auto &sm = back::sub_sm<back::sm_impl<T>>::get(&subs);
2376  while (sm.process_internal_events(back::anonymous{}, deps, subs)) {
2377  }
2378 }
2379 template <class S1, class S2, class E, class G, class A>
2380 struct transition<state<S1>, state<S2>, front::event<E>, G, A> {
2381  static constexpr auto initial = state<S2>::initial;
2382  static constexpr auto history = state<S2>::history;
2383  using src_state = typename state<S2>::type;
2384  using dst_state = typename state<S1>::type;
2385  using event = E;
2386  using guard = G;
2387  using action = A;
2388  using deps = aux::apply_t<aux::unique_t, aux::join_t<get_deps_t<G, E>, get_deps_t<A, E>>>;
2389  transition(const G &g, const A &a) : g(g), a(a) {}
2390  template <class TEvent, class SM, class TDeps, class TSubs>
2391  bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state, aux::true_type) {
2392  if (call<TEvent, args_t<G, TEvent>, typename SM::logger_t>::execute(g, event, sm, deps, subs)) {
2393  sm.process_internal_event(back::on_exit<back::_, TEvent>{event}, deps, subs, current_state);
2394  update_current_state(sm, deps, subs, current_state,
2395  aux::get_id<typename SM::state_t, dst_state>((typename SM::states_ids_t *)0), state<src_state>{},
2396  state<dst_state>{});
2397  call<TEvent, args_t<A, TEvent>, typename SM::logger_t>::execute(a, event, sm, deps, subs);
2398  sm.process_internal_event(back::on_entry<back::_, TEvent>{event}, deps, subs, current_state);
2399  process_internal_transitions(deps, subs, state<dst_state>{});
2400  return true;
2401  }
2402  return false;
2403  }
2404  template <class TEvent, class SM, class TDeps, class TSubs>
2405  bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state, aux::false_type) {
2406  if (call<TEvent, args_t<G, TEvent>, typename SM::logger_t>::execute(g, event, sm, deps, subs)) {
2407  update_current_state(sm, deps, subs, current_state,
2408  aux::get_id<typename SM::state_t, dst_state>((typename SM::states_ids_t *)0), state<src_state>{},
2409  state<dst_state>{});
2410  call<TEvent, args_t<A, TEvent>, typename SM::logger_t>::execute(a, event, sm, deps, subs);
2411  process_internal_transitions(deps, subs, state<dst_state>{});
2412  return true;
2413  }
2414  return false;
2415  }
2416  G g;
2417  A a;
2418 };
2419 template <class S2, class E, class G, class A>
2420 struct transition<state<internal>, state<S2>, front::event<E>, G, A> {
2421  static constexpr auto initial = state<S2>::initial;
2422  static constexpr auto history = state<S2>::history;
2423  using src_state = typename state<S2>::type;
2424  using dst_state = internal;
2425  using event = E;
2426  using guard = G;
2427  using action = A;
2428  using deps = aux::apply_t<aux::unique_t, aux::join_t<get_deps_t<G, E>, get_deps_t<A, E>>>;
2429  transition(const G &g, const A &a) : g(g), a(a) {}
2430  template <class TEvent, class SM, class TDeps, class TSubs, class... Ts>
2431  bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &, Ts &&...) {
2432  if (call<TEvent, args_t<G, TEvent>, typename SM::logger_t>::execute(g, event, sm, deps, subs)) {
2433  call<TEvent, args_t<A, TEvent>, typename SM::logger_t>::execute(a, event, sm, deps, subs);
2434  return true;
2435  }
2436  return false;
2437  }
2438  G g;
2439  A a;
2440 };
2441 template <class S1, class S2, class E, class A>
2442 struct transition<state<S1>, state<S2>, front::event<E>, always, A> {
2443  static constexpr auto initial = state<S2>::initial;
2444  static constexpr auto history = state<S2>::history;
2445  using src_state = typename state<S2>::type;
2446  using dst_state = typename state<S1>::type;
2447  using event = E;
2448  using guard = always;
2449  using action = A;
2450  using deps = aux::apply_t<aux::unique_t, get_deps_t<A, E>>;
2451  transition(const always &, const A &a) : a(a) {}
2452  template <class TEvent, class SM, class TDeps, class TSubs>
2453  bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state, aux::true_type) {
2454  sm.process_internal_event(back::on_exit<back::_, TEvent>{event}, deps, subs, current_state);
2455  update_current_state(sm, deps, subs, current_state,
2456  aux::get_id<typename SM::state_t, dst_state>((typename SM::states_ids_t *)0), state<src_state>{},
2457  state<dst_state>{});
2458  call<TEvent, args_t<A, TEvent>, typename SM::logger_t>::execute(a, event, sm, deps, subs);
2459  sm.process_internal_event(back::on_entry<back::_, TEvent>{event}, deps, subs, current_state);
2460  process_internal_transitions(deps, subs, state<dst_state>{});
2461  return true;
2462  }
2463  template <class TEvent, class SM, class TDeps, class TSubs>
2464  bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state, aux::false_type) {
2465  update_current_state(sm, deps, subs, current_state,
2466  aux::get_id<typename SM::state_t, dst_state>((typename SM::states_ids_t *)0), state<src_state>{},
2467  state<dst_state>{});
2468  call<TEvent, args_t<A, TEvent>, typename SM::logger_t>::execute(a, event, sm, deps, subs);
2469  process_internal_transitions(deps, subs, state<dst_state>{});
2470  return true;
2471  }
2472  A a;
2473 };
2474 template <class S2, class E, class A>
2475 struct transition<state<internal>, state<S2>, front::event<E>, always, A> {
2476  static constexpr auto initial = state<S2>::initial;
2477  static constexpr auto history = state<S2>::history;
2478  using src_state = typename state<S2>::type;
2479  using dst_state = internal;
2480  using event = E;
2481  using guard = always;
2482  using action = A;
2483  using deps = aux::apply_t<aux::unique_t, get_deps_t<A, E>>;
2484  transition(const always &, const A &a) : a(a) {}
2485  template <class TEvent, class SM, class TDeps, class TSubs, class... Ts>
2486  bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &, Ts &&...) {
2487  call<TEvent, args_t<A, TEvent>, typename SM::logger_t>::execute(a, event, sm, deps, subs);
2488  return true;
2489  }
2490  A a;
2491 };
2492 template <class S1, class S2, class E, class G>
2493 struct transition<state<S1>, state<S2>, front::event<E>, G, none> {
2494  static constexpr auto initial = state<S2>::initial;
2495  static constexpr auto history = state<S2>::history;
2496  using src_state = typename state<S2>::type;
2497  using dst_state = typename state<S1>::type;
2498  using event = E;
2499  using guard = G;
2500  using action = none;
2501  using deps = aux::apply_t<aux::unique_t, get_deps_t<G, E>>;
2502  transition(const G &g, const none &) : g(g) {}
2503  template <class TEvent, class SM, class TDeps, class TSubs>
2504  bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state, aux::true_type) {
2505  if (call<TEvent, args_t<G, TEvent>, typename SM::logger_t>::execute(g, event, sm, deps, subs)) {
2506  sm.process_internal_event(back::on_exit<back::_, TEvent>{event}, deps, subs, current_state);
2507  update_current_state(sm, deps, subs, current_state,
2508  aux::get_id<typename SM::state_t, dst_state>((typename SM::states_ids_t *)0), state<src_state>{},
2509  state<dst_state>{});
2510  sm.process_internal_event(back::on_entry<back::_, TEvent>{event}, deps, subs, current_state);
2511  process_internal_transitions(deps, subs, state<dst_state>{});
2512  return true;
2513  }
2514  return false;
2515  }
2516  template <class TEvent, class SM, class TDeps, class TSubs>
2517  bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state, aux::false_type) {
2518  if (call<TEvent, args_t<G, TEvent>, typename SM::logger_t>::execute(g, event, sm, deps, subs)) {
2519  update_current_state(sm, deps, subs, current_state,
2520  aux::get_id<typename SM::state_t, dst_state>((typename SM::states_ids_t *)0), state<src_state>{},
2521  state<dst_state>{});
2522  process_internal_transitions(deps, subs, state<dst_state>{});
2523  return true;
2524  }
2525  return false;
2526  }
2527  G g;
2528 };
2529 template <class S2, class E, class G>
2530 struct transition<state<internal>, state<S2>, front::event<E>, G, none> {
2531  static constexpr auto initial = state<S2>::initial;
2532  static constexpr auto history = state<S2>::history;
2533  using src_state = typename state<S2>::type;
2534  using dst_state = internal;
2535  using event = E;
2536  using guard = G;
2537  using action = none;
2538  using deps = aux::apply_t<aux::unique_t, get_deps_t<G, E>>;
2539  transition(const G &g, const none &) : g(g) {}
2540  template <class TEvent, class SM, class TDeps, class TSubs, class... Ts>
2541  bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &, Ts &&...) {
2542  return call<TEvent, args_t<G, TEvent>, typename SM::logger_t>::execute(g, event, sm, deps, subs);
2543  }
2544  G g;
2545 };
2546 template <class S1, class S2, class E>
2547 struct transition<state<S1>, state<S2>, front::event<E>, always, none> {
2548  static constexpr auto initial = state<S2>::initial;
2549  static constexpr auto history = state<S2>::history;
2550  using src_state = typename state<S2>::type;
2551  using dst_state = typename state<S1>::type;
2552  using event = E;
2553  using guard = always;
2554  using action = none;
2555  using deps = aux::type_list<>;
2556  transition(const always &, const none &) {}
2557  template <class TEvent, class SM, class TDeps, class TSubs>
2558  bool execute(const TEvent &event, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state, aux::true_type) {
2559  sm.process_internal_event(back::on_exit<back::_, TEvent>{event}, deps, subs, current_state);
2560  update_current_state(sm, deps, subs, current_state,
2561  aux::get_id<typename SM::state_t, dst_state>((typename SM::states_ids_t *)0), state<src_state>{},
2562  state<dst_state>{});
2563  sm.process_internal_event(back::on_entry<back::_, TEvent>{event}, deps, subs, current_state);
2564  process_internal_transitions(deps, subs, state<dst_state>{});
2565  return true;
2566  }
2567  template <class TEvent, class SM, class TDeps, class TSubs>
2568  bool execute(const TEvent &, SM &sm, TDeps &deps, TSubs &subs, typename SM::state_t &current_state, aux::false_type) {
2569  update_current_state(sm, deps, subs, current_state,
2570  aux::get_id<typename SM::state_t, dst_state>((typename SM::states_ids_t *)0), state<src_state>{},
2571  state<dst_state>{});
2572  process_internal_transitions(deps, subs, state<dst_state>{});
2573  return true;
2574  }
2575  __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
2576 };
2577 template <class S2, class E>
2578 struct transition<state<internal>, state<S2>, front::event<E>, always, none> {
2579  static constexpr auto initial = state<S2>::initial;
2580  static constexpr auto history = state<S2>::history;
2581  using src_state = typename state<S2>::type;
2582  using dst_state = internal;
2583  using event = E;
2584  using guard = always;
2585  using action = none;
2586  using deps = aux::type_list<>;
2587  transition(const always &, const none &) {}
2588  template <class TEvent, class SM, class TDeps, class TSubs, class... Ts>
2589  bool execute(const TEvent &, SM &, TDeps &, TSubs &, typename SM::state_t &, Ts &&...) {
2590  return true;
2591  }
2592  __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
2593 };
2594 }
2595 using _ = back::_;
2596 #if !defined(COMPILING_WITH_MSVC)
2597 template <class TEvent>
2598 constexpr front::event<TEvent> event{};
2599 #else
2600 template <class TEvent>
2601 front::event<TEvent> event __BOOST_SML_VT_INIT;
2602 #endif
2603 template <class TEvent>
2604 __BOOST_SML_UNUSED front::event<back::on_entry<_, TEvent>> on_entry __BOOST_SML_VT_INIT;
2605 template <class TEvent>
2606 __BOOST_SML_UNUSED front::event<back::on_exit<_, TEvent>> on_exit __BOOST_SML_VT_INIT;
2607 template <class TEvent>
2608 front::event<back::unexpected_event<TEvent>> unexpected_event __BOOST_SML_VT_INIT;
2609 template <class T>
2610 front::event<back::exception<T>> exception __BOOST_SML_VT_INIT;
2611 using anonymous = back::anonymous;
2612 using initial = back::initial;
2613 #if !defined(COMPILING_WITH_MSVC)
2614 template <class T>
2615 constexpr typename front::state_sm<T>::type state{};
2616 #else
2617 template <class T>
2618 typename front::state_sm<T>::type state __BOOST_SML_VT_INIT;
2619 #endif
2620 inline namespace literals {
2621 #if !defined(COMPILING_WITH_MSVC)
2622 template <class T, T... Chrs>
2623 constexpr auto operator""_s() {
2624  return front::state<aux::string<T, Chrs...>>{};
2625 }
2626 template <class T, T... Chrs>
2627 constexpr auto operator""_e() {
2628  return event<aux::string<T, Chrs...>>;
2629 }
2630 #endif
2631 }
2632 __BOOST_SML_UNUSED static front::state<back::terminate_state> X;
2633 __BOOST_SML_UNUSED static front::history_state H;
2634 __BOOST_SML_UNUSED static front::actions::defer defer;
2635 __BOOST_SML_UNUSED static front::actions::process process;
2636 template <class... Ts, __BOOST_SML_REQUIRES(aux::is_same<aux::bool_list<aux::always<Ts>::value...>,
2637  aux::bool_list<concepts::transitional<Ts>::value...>>::value)>
2638 auto make_transition_table(Ts... ts) {
2639  return aux::pool<Ts...>{ts...};
2640 }
2641 BOOST_SML_NAMESPACE_END
2642 #undef __BOOST_SML_UNUSED
2643 #undef __BOOST_SML_VT_INIT
2644 #undef __BOOST_SML_ZERO_SIZE_ARRAY
2645 #undef __BOOST_SML_ZERO_SIZE_ARRAY_CREATE
2646 #undef __BOOST_SML_TEMPLATE_KEYWORD
2647 #if defined(__clang__)
2648 #pragma clang diagnostic pop
2649 #elif defined(__GNUC__) && defined(__BOOST_SML_DEFINED_HAS_BUILTIN)
2650 #undef __has_builtin
2651 #pragma GCC diagnostic pop
2652 #elif defined(COMPILING_WITH_MSVC) && defined(__BOOST_SML_DEFINED_HAS_BUILTIN)
2653 #undef __has_builtin
2654 #undef __has_builtin__make_integer_seq
2655 #endif
2656 #undef COMPILING_WITH_MSVC
2657 #endif
2658 #endif
ROSCPP_DECL void start()
ROSCONSOLE_DECL void initialize()
void init(const M_string &remappings)
bool call(const std::string &service_name, MReq &req, MRes &res)
ROSCPP_DECL bool execute(const std::string &method, const XmlRpc::XmlRpcValue &request, XmlRpc::XmlRpcValue &response, XmlRpc::XmlRpcValue &payload, bool wait_for_master)


boost_sml
Author(s): boost-experimental (https://github.com/boost-experimental)
autogenerated on Thu Jan 26 2023 03:14:02