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