Skip to content

Commit fde53fe

Browse files
Edvard Vasdalkris-jusiak
authored andcommitted
fix: fallback to any_state when state-specific guard fails
1 parent 026dfd7 commit fde53fe

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

include/boost/sml.hpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,9 +1136,15 @@ template <class T, class, class... Ts>
11361136
transitions<Ts...> get_state_mapping_impl(state_mappings<T, aux::type_list<Ts...>> *);
11371137
template <class T, class TMappings, class TUnexpected>
11381138
struct get_state_mapping {
1139-
using type = aux::conditional_t<aux::is_same<decltype(get_state_mapping_impl<T, TUnexpected>((TMappings *)0)), transitions<TUnexpected>>::value,
1140-
decltype(get_state_mapping_impl<_, TUnexpected>((TMappings *)0)),
1141-
decltype(get_state_mapping_impl<T, TUnexpected>((TMappings *)0))>;
1139+
using state_mapping = decltype(get_state_mapping_impl<T, TUnexpected>((TMappings *)0));
1140+
using any_state_mapping = decltype(get_state_mapping_impl<_, TUnexpected>((TMappings *)0));
1141+
struct type {
1142+
template <class TEvent, class TSm, class TDeps, class TSubs>
1143+
constexpr static bool execute(const TEvent& event, TSm& sm, TDeps& deps, TSubs& subs, typename TSm::state_t& current_state) {
1144+
return state_mapping::template execute<TEvent, TSm, TDeps, TSubs>(event, sm, deps, subs, current_state) ||
1145+
any_state_mapping::template execute<TEvent, TSm, TDeps, TSubs>(event, sm, deps, subs, current_state);
1146+
}
1147+
};
11421148
};
11431149
template <class S>
11441150
transitions_sub<S> get_sub_state_mapping_impl(...);

test/ft/states.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,44 @@ test any_state_nested = [] {
317317
expect("a1|a2|a3|" == c_.calls);
318318
};
319319

320+
test any_state_fallback_when_guard_fails = [] {
321+
struct c {
322+
auto operator()() {
323+
using namespace sml;
324+
auto action1 = [this]{ calls += "a1|"; };
325+
auto action2 = [this]{ calls += "a2|"; };
326+
327+
auto true_guard = []{ return true; };
328+
auto false_guard = []{ return false; };
329+
330+
// clang-format off
331+
return make_transition_table(
332+
*idle + event<e1> = s1,
333+
s1 + event<e2> [ false_guard ] = s2,
334+
335+
any + event<e1> / action1,
336+
any + event<e2> / action2
337+
338+
);
339+
// clang-format on
340+
}
341+
342+
std::string calls{};
343+
};
344+
345+
sml::sm<c> sm{};
346+
const c& c_ = sm;
347+
348+
sm.process_event(e1());
349+
expect(sm.is(s1));
350+
sm.process_event(e1());
351+
expect(sm.is(s1));
352+
sm.process_event(e2());
353+
expect(sm.is(s1));
354+
355+
expect("a1|a2|" == c_.calls);
356+
};
357+
320358
#if !defined(_MSC_VER)
321359
test state_names = [] {
322360
struct c {

0 commit comments

Comments
 (0)