Skip to content

Commit cd3ef80

Browse files
Edvard Vasdalkris-jusiak
authored andcommitted
Handling the any state correctly when using a nested state machine
1 parent 0bdc4f5 commit cd3ef80

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

include/boost/sml.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,15 @@ template <class T, class... Ts>
11371137
transitions_sub<T, Ts...> get_sub_state_mapping_impl(state_mappings<T, aux::type_list<Ts...>> *);
11381138
template <class T, class TMappings, class TUnexpected>
11391139
struct get_state_mapping<sm<T>, TMappings, TUnexpected> {
1140-
using type = decltype(get_sub_state_mapping_impl<sm<T>>((TMappings *)0));
1140+
using sub_sm_mapping = decltype(get_sub_state_mapping_impl<sm<T>>((TMappings *)0));
1141+
using fallback_event_mapping = decltype(get_state_mapping_impl<_, TUnexpected>((TMappings *)0));
1142+
struct type : sub_sm_mapping {
1143+
template <class TEvent, class TSm, class TDeps, class TSubs>
1144+
constexpr static bool execute(const TEvent& event, TSm& sm, TDeps& deps, TSubs& subs, typename TSm::state_t& current_state) {
1145+
return sub_sm_mapping::template execute<TEvent, TSm, TDeps, TSubs>(event, sm, deps, subs, current_state) ||
1146+
fallback_event_mapping::template execute<TEvent, TSm, TDeps, TSubs>(event, sm, deps, subs, current_state);
1147+
}
1148+
};
11411149
};
11421150
template <class T, class TMappings, class TUnexpected>
11431151
using get_state_mapping_t = typename get_state_mapping<T, TMappings, TUnexpected>::type;

test/ft/states.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,62 @@ test any_state = [] {
261261
expect("a1|a1|a2|a3|" == c_.calls);
262262
};
263263

264+
test any_state_nested = [] {
265+
struct s {
266+
auto operator()() noexcept {
267+
using namespace sml;
268+
auto action1 = [this]{ calls += "a1|"; };
269+
// clang-format off
270+
return make_transition_table(
271+
*idle + event<e1> / action1 = s1
272+
);
273+
// clang-format on
274+
}
275+
std::string& calls;
276+
};
277+
278+
struct c {
279+
auto operator()() noexcept {
280+
using namespace sml;
281+
auto action2 = [this]{ calls += "a2|"; };
282+
auto action3 = [this]{ calls += "a3|"; };
283+
// clang-format off
284+
return make_transition_table(
285+
any + event<e2> / action2,
286+
any + event<e3> / action3 = idle,
287+
*idle + event<e1> = state<s>,
288+
state<s> + event<e4> = s2
289+
);
290+
// clang-format on
291+
}
292+
std::string& calls;
293+
};
294+
295+
auto calls = std::string{};
296+
auto c_ = c{calls};
297+
auto s_ = s{calls};
298+
299+
sml::sm<c> sm{c_, s_};
300+
301+
sm.process_event(e1());
302+
expect(sm.is(sml::state<s>));
303+
expect(sm.is<decltype(sml::state<s>)>(idle));
304+
305+
sm.process_event(e1());
306+
expect(sm.is(sml::state<s>));
307+
expect(sm.is<decltype(sml::state<s>)>(s1));
308+
expect("a1|" == c_.calls);
309+
310+
sm.process_event(e2());
311+
expect(sm.is(sml::state<s>));
312+
expect(sm.is<decltype(sml::state<s>)>(s1));
313+
expect("a1|a2|" == c_.calls);
314+
315+
sm.process_event(e3());
316+
expect(sm.is(idle));
317+
expect("a1|a2|a3|" == c_.calls);
318+
};
319+
264320
#if !defined(_MSC_VER)
265321
test state_names = [] {
266322
struct c {

0 commit comments

Comments
 (0)