Maki
Loading...
Searching...
No Matches
transition_table.hpp
1//Copyright Florian Goujeon 2021 - 2025.
2//Distributed under the Boost Software License, Version 1.0.
3//(See accompanying file LICENSE or copy at
4//https://www.boost.org/LICENSE_1_0.txt)
5//Official repository: https://github.com/fgoujeon/maki
6
11
12#ifndef MAKI_TRANSITION_TABLE_HPP
13#define MAKI_TRANSITION_TABLE_HPP
14
15#include "action.hpp"
16#include "guard.hpp"
17#include "event_set.hpp"
18#include "state_set.hpp"
19#include "states.hpp"
20#include "init.hpp"
21#include "final.hpp"
22#include "null.hpp"
23#include "detail/impl.hpp"
24#include "detail/state_builder_fwd.hpp"
25#include "detail/tuple.hpp"
26
27namespace maki
28{
29
30namespace detail
31{
32 template<class... Transitions>
33 struct transition_table_impl
34 {
35 static constexpr auto size = sizeof...(Transitions);
36 tuple<Transitions...> transitions;
37 };
38}
39
40#ifdef MAKI_DETAIL_DOXYGEN
60template<class Impl = IMPLEMENTATION_DETAIL>
62#else
63template<class Impl = detail::transition_table_impl<>>
65#endif
66
67namespace detail
68{
69 template
70 <
71 class SourceStateBuilder,
72 class TargetStateBuilder,
73 class EventSet,
74 action_signature ActionSignature,
75 class ActionCallable,
76 guard_signature GuardSignature,
77 class GuardCallable
78 >
79 struct transition
80 {
81 SourceStateBuilder source_state_builder;
82 TargetStateBuilder target_state_builder;
83 EventSet evt_set;
84 action<ActionSignature, ActionCallable> act;
85 guard<GuardSignature, GuardCallable> grd;
86 };
87
88 template
89 <
90 class SourceStateBuilder,
91 class TargetStateBuilder,
92 class EventSet,
93 action_signature ActionSignature,
94 class ActionCallable,
95 guard_signature GuardSignature,
96 class GuardCallable
97 >
98 transition
99 (
100 SourceStateBuilder,
101 TargetStateBuilder,
102 EventSet,
103 action<ActionSignature, ActionCallable>,
104 guard<GuardSignature, GuardCallable>
105 ) -> transition
106 <
107 SourceStateBuilder,
108 TargetStateBuilder,
109 EventSet,
110 ActionSignature,
111 ActionCallable,
112 GuardSignature,
113 GuardCallable
114 >;
115
116 template<class... Transitions>
117 constexpr auto make_transition_table(const tuple<Transitions...>& transitions)
118 {
119 using impl_t = transition_table_impl<Transitions...>;
120 return transition_table<impl_t>{impl_t{transitions}};
121 }
122
123 template<class Impl>
124 constexpr const auto& rows(const transition_table<Impl>& table)
125 {
126 return impl_of(table).transitions;
127 }
128
129 template<class T>
130 constexpr decltype(auto) store_state_builder(T&& obj)
131 {
132 return std::forward<T>(obj);
133 }
134
135 //Store a pointer in this case
136 constexpr auto store_state_builder(init_t /*init*/)
137 {
138 return &detail::state_builders::null;
139 }
140
141 //Store a pointer in this case
142 constexpr auto store_state_builder(final_t /*init*/)
143 {
144 return &detail::state_builders::final;
145 }
146
147 //Store a pointer in this case
148 template<class OptionSet>
149 constexpr auto store_state_builder(const state_builder<OptionSet>& builder)
150 {
151 return &builder;
152 }
153}
154
155template<class Impl>
157{
158public:
162 constexpr transition_table() = default;
163
167 constexpr transition_table(const transition_table&) = default;
168
173
174 ~transition_table() = default;
175
180
185
195 template
196 <
197 class Source,
198 class Target,
199 class EventSet = null_t,
200 class ActionOrNull = null_t,
201 class GuardOrNull = null_t
202 >
203 constexpr auto operator()
204 (
205 const Source& source_state_builder,
206 const Target& target_state_builder,
207 const EventSet& evt_set = null,
208 const ActionOrNull& action = null,
209 const GuardOrNull& guard = null
210 )
211 {
212 //Check source
213 if constexpr(Impl::size == 0)
214 {
215 static_assert
216 (
217 detail::is_init_v<Source>,
218 "Source (1st argument) of first transition must be `maki::init`. (Note: Composite state regions without initial pseudostate are not implemented yet.)"
219 );
220 }
221 else
222 {
223 static_assert
224 (
225 detail::is_state_builder_v<Source> || detail::is_state_set_v<Source>,
226 "Source (1st argument) must be an instance of `maki::state_builder` or an instance of `maki::state_set`"
227 );
228 }
229
230 //Check target
231 if constexpr(detail::is_init_v<Source>)
232 {
233 static_assert
234 (
235 detail::is_state_builder_v<Target>,
236 "Target (2nd argument) of transition from initial pseudostate must be an instance of `maki::state_builder`."
237 );
238 }
239 else
240 {
241 static_assert
242 (
243 detail::is_state_builder_v<Target> || detail::is_null_v<Target> || detail::is_final_v<Target>,
244 "Target (2nd argument) must be an instance of `maki::state_builder`, `maki::null` or `maki::final`."
245 );
246 }
247
248 //Check event
249 if constexpr(detail::is_init_v<Source>)
250 {
251 static_assert
252 (
253 detail::is_null_v<EventSet>,
254 "Event (3rd argument) of transition from initial pseudostate must be `maki::null`"
255 );
256 }
257 else
258 {
259 static_assert
260 (
261 detail::is_event_v<EventSet> || detail::is_event_set_v<EventSet> || detail::is_null_v<EventSet>,
262 "Event (3rd argument) must be an instance of `maki::event_t`, an instance of `maki::event_set`, or `maki::null`"
263 );
264 }
265
266 //Check action
267 static_assert
268 (
269 detail::is_action_v<ActionOrNull> || detail::is_null_v<ActionOrNull>,
270 "Action (4th argument) must be an instance of `maki::action` or `maki::null`."
271 );
272
273 //Check guard
274 if constexpr(detail::is_init_v<Source>)
275 {
276 static_assert
277 (
278 detail::is_null_v<GuardOrNull>,
279 "Guard (5th argument) of transition from initial pseudostate must be `maki::null`."
280 );
281 }
282 else
283 {
284 static_assert
285 (
286 detail::is_guard_v<GuardOrNull> || detail::is_null_v<GuardOrNull>,
287 "Guard (5th argument) must be an instance of `maki::guard` or `maki::null`."
288 );
289 }
290
291 return detail::make_transition_table
292 (
293 tuple_append
294 (
295 impl_.transitions,
296 detail::transition
297 {
298 detail::store_state_builder(source_state_builder),
299 detail::store_state_builder(target_state_builder),
300 evt_set,
301 detail::to_action(action),
302 detail::to_guard(guard)
303 }
304 )
305 );
306 }
307
308private:
309 using impl_type = Impl;
310
311#ifndef MAKI_DETAIL_DOXYGEN
312 template<class... Transitions>
313 friend constexpr auto detail::make_transition_table(const detail::tuple<Transitions...>&);
314#endif
315
316 constexpr explicit transition_table(const Impl& impl):
317 impl_{impl}
318 {
319 }
320
321 MAKI_DETAIL_FRIENDLY_IMPL
322};
323
324} //namespace
325
326#endif
Represents a transition table.
Definition transition_table.hpp:157
constexpr transition_table(const transition_table &)=default
Copy constructor.
transition_table & operator=(transition_table &&)=delete
Deleted move operator.
transition_table(transition_table &&)=delete
Deleted move constructor.
transition_table & operator=(const transition_table &)=delete
Deleted assignment operator.
constexpr transition_table()=default
Default constructor.
The Maki library.
IMPLEMENTATION_DETAIL init_t
The type of maki::init
Definition init.hpp:19
IMPLEMENTATION_DETAIL final_t
The type of maki::final
Definition final.hpp:19
IMPLEMENTATION_DETAIL null_t
The type of maki::null
Definition null.hpp:26
guard_signature
The set of arguments taken by a guard callable.
Definition guard.hpp:26
action_signature
The set of arguments taken by an action callable.
Definition action.hpp:26
Represents an action to be given to maki::transition_table.
Definition action.hpp:60
Represents a guard to be given to maki::transition_table. Use the builder functions (maki::guard_v() ...
Definition guard.hpp:86