fsm
state.h
Go to the documentation of this file.
1 
19 #pragma once
20 
21 #include <optional>
22 #include <type_traits>
23 
24 #include "../base/type_traits.h"
25 #include "transition.h"
26 
27 namespace escad {
56 namespace new_fsm {
57 
58 namespace detail {
59 
60 struct NoContext {};
61 
62 struct InternalEvent {};
63 
71 template <typename Target, typename = void>
72 struct has_onEnter : std::false_type {};
73 
79 template <typename Target>
80 struct has_onEnter<Target,
81  std::void_t<decltype(std::declval<Target>().onEnter())>>
82  : std::true_type {};
83 
89 template <class T> inline constexpr bool has_onEnter_v = has_onEnter<T>::value;
90 
100 template <typename Target, typename Event, typename = void>
101 struct has_onEnterWithEvent : std::false_type {};
102 
111 template <typename Target, typename Event>
112 struct has_onEnterWithEvent<Target, Event,
113  std::void_t<decltype(std::declval<Target>().onEnter(
114  std::declval<Event>()))>> : std::true_type {};
115 
123 template <class T, class E>
124 inline constexpr bool has_onEnterWithEvent_v =
126 
127 template <typename Target, typename = void>
128 struct has_onExit : std::false_type {};
129 
130 template <typename Target>
131 struct has_onExit<Target,
132  std::void_t<decltype(std::declval<Target>().onExit())>>
133  : std::true_type {};
134 
135 template <class T> inline constexpr bool has_onExit_v = has_onExit<T>::value;
136 
146 template <typename Target, typename Event, typename = void>
147 struct has_transitionTo : std::false_type {};
148 
157 template <typename Target, typename Event>
159  Target, Event,
160  std::void_t<decltype(std::declval<Target>().transitionTo(
161  std::declval<Event>()))>> : std::true_type {};
162 
170 template <class T, class E>
171 inline constexpr bool has_transitionTo_v = has_transitionTo<T, E>::value;
172 
173 template <typename Target, typename = void>
174 struct has_transitionInternalTo : std::false_type {};
175 
176 template <typename Target>
178  Target,
179  std::void_t<decltype(std::declval<Target>().transitionInternalTo())>>
180  : std::true_type {};
181 
182 template <class T>
183 inline constexpr bool has_transitionInternalTo_v =
185 
186 } // namespace detail
187 
191 template <class... S> struct states {
192  using type_list = mpl::type_list<S...>;
193  static constexpr auto count = type_list::size;
194 };
195 
202 template <class Derived, class Context = detail::NoContext> struct state {
203  using ctx = Context;
204 
205  // state() : context_{} {}
206  state(Context &context) : context_(context) {}
207 
216  template <class Target = Derived, class Event>
217  bool enter(const Event &event) {
218  if constexpr (detail::has_onEnterWithEvent_v<Target, Event>) {
219  static_cast<Target *>(this)->onEnter(event);
220  return true;
221  }
222  return false;
223  }
224 
233  template <class Target = Derived> bool enter() {
234  if constexpr (detail::has_onEnter_v<Target>) {
235  static_cast<Target *>(this)->onEnter();
236  return true;
237  }
238  return false;
239  }
240 
241  template <class Target = Derived> bool exit() {
242  if constexpr (detail::has_onExit_v<Target>) {
243  static_cast<Target *>(this)->doRun();
244  return true;
245  }
246  return false;
247  }
248 
257  template <class Target = Derived, class Event>
258  auto transition(const Event &event)
259  -> decltype(std::declval<Target>().transitionTo(event)) {
260  if constexpr (detail::has_transitionTo_v<Target, Event>) {
261  return static_cast<Target *>(this)->transitionTo(event);
262  }
263  }
264 
272  template <class Target = Derived>
274  return detail::none{};
275  }
276 
283  template <class Target = Derived>
285  -> decltype(std::declval<Target>().transitionInternalTo()) {
286  if constexpr (detail::has_transitionInternalTo_v<Target>) {
287  return static_cast<Target *>(this)->transitionInternalTo();
288  }
289  // return detail::none{};
290  }
291 
292  // template <class Target = Derived>
293  // auto transitionInternal(...) -> transitions<detail::none> {
294  // return detail::none{};
295  // }
296 
297  template <class Event> bool dispatch(const Event &) { return false; }
298 
299  const Context &context() { return context_; }
300 
301 protected:
306 };
307 
308 } // namespace new_fsm
309 } // namespace escad
Defines the transitions class and related helper functions.
Definition: testJsonContexts.cpp:18
auto transition(...) -> transitions< detail::none >
For non-existing transitionTo() methods.
Definition: state.h:273
Tag type indicating no transition.
Definition: transition.h:24
auto transition(const Event &event) -> decltype(std::declval< Target >().transitionTo(event))
Calls transitionTo(const Event &event) of Derived if it exists.
Definition: state.h:258
Definition: compressed_pair.h:255
Definition: state.h:60
Class representing a collection of transitions.
Definition: transition.h:50
bool enter(const Event &event)
Calls onEnter(const Event &event) of Derived if it exists.
Definition: state.h:217
Base class for an event.
Definition: states.h:31
Default case of helper for detecting if type Target has a onEnter(const Event &) method.
Definition: state.h:101
auto transitionInternal() -> decltype(std::declval< Target >().transitionInternalTo())
Calls transitionInternalTo() of Derived if it exists.
Definition: state.h:284
Default case of helper for detecting if type Target has a onEnter() method.
Definition: state.h:72
state is a CRTP base class for states.
Definition: state.h:202
bool enter()
Calls onEnter() of Derived if it exists.
Definition: state.h:233
Defines a set of states.
Definition: state.h:191
Definition: compressed_pair.h:10
Alias template to facilitate the creation of named values.
Definition: type_traits.h:142
Context & context_
Reference to the Context.
Definition: state.h:305
Definition: state.h:128
Default case of helper for detecting if type Target has a transitionTo(const Event &) method...
Definition: state.h:147