diff --git a/include/boost/sml.hpp b/include/boost/sml.hpp index 87f0c049..ef2339e4 100644 --- a/include/boost/sml.hpp +++ b/include/boost/sml.hpp @@ -3224,13 +3224,13 @@ struct transition_sa, A> : transition, state, fron } }; template -struct transition, front::event> { +struct transition, front::event> : transition, state, front::event, always, none> { + constexpr transition(const state &, const front::event &) + : transition, state, front::event, always, none>{always{}, none{}} {} template constexpr auto operator=(const T &) const { return transition, front::event, always, none>{always{}, none{}}; } - const state &s2; - front::event e; }; template struct transition_eg, G> { diff --git a/test/ft/CMakeLists.txt b/test/ft/CMakeLists.txt index 91fdd47b..4bbe9ec3 100644 --- a/test/ft/CMakeLists.txt +++ b/test/ft/CMakeLists.txt @@ -155,6 +155,11 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/issue_552_sub_sm_dep_identity.cpp) add_test(test_issue_552_sub_sm_dep_identity test_issue_552_sub_sm_dep_identity) endif() +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/issue_317_bare_internal_transition.cpp) + add_executable(test_issue_317_bare_internal_transition issue_317_bare_internal_transition.cpp) + add_test(test_issue_317_bare_internal_transition test_issue_317_bare_internal_transition) +endif() + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/issue_473_defer_anonymous.cpp) add_executable(test_issue_473_defer_anonymous issue_473_defer_anonymous.cpp) add_test(test_issue_473_defer_anonymous test_issue_473_defer_anonymous) diff --git a/test/ft/issue_317_bare_internal_transition.cpp b/test/ft/issue_317_bare_internal_transition.cpp new file mode 100644 index 00000000..0be0be90 --- /dev/null +++ b/test/ft/issue_317_bare_internal_transition.cpp @@ -0,0 +1,65 @@ +// cppcheck-suppress missingIncludeSystem +#include + +namespace sml = boost::sml; + +namespace { +struct ignored {}; +struct leave {}; +struct come_back {}; + +struct counters { + int entries = 0; + int exits = 0; +}; +struct count_entry { + void operator()(counters &c) const { ++c.entries; } +}; +struct count_exit { + void operator()(counters &c) const { ++c.exits; } +}; + +const auto idle = sml::state; +const auto busy = sml::state; +} // namespace + +test bare_row_on_initial_state_consumes_event_without_exit_or_entry = [] { + struct c { + auto operator()() const noexcept { + using namespace sml; + return make_transition_table(*idle + event, idle + event = busy, busy + event = idle, + idle + sml::on_entry<_> / count_entry{}, idle + sml::on_exit<_> / count_exit{}); + } + }; + counters calls{}; + sml::sm sm{calls}; + expect(1 == calls.entries); + + expect(sm.process_event(ignored{})); + expect(sm.is(idle)); + expect(1 == calls.entries); + expect(0 == calls.exits); + + expect(!sm.process_event(come_back{})); + expect(sm.is(idle)); +}; + +test bare_row_on_non_initial_state_consumes_event_without_exit_or_entry = [] { + struct c { + auto operator()() const noexcept { + using namespace sml; + return make_transition_table(*idle + event = busy, busy + event, busy + sml::on_entry<_> / count_entry{}, + busy + sml::on_exit<_> / count_exit{}); + } + }; + counters calls{}; + sml::sm sm{calls}; + expect(sm.process_event(leave{})); + expect(sm.is(busy)); + expect(1 == calls.entries); + + expect(sm.process_event(ignored{})); + expect(sm.is(busy)); + expect(1 == calls.entries); + expect(0 == calls.exits); +};