From da8a0cc60c53b0ea459b7cdae8d0b1e0053b4a44 Mon Sep 17 00:00:00 2001 From: Kris Jusiak Date: Tue, 26 May 2020 10:49:52 -0600 Subject: [PATCH] :new: [example] State names visitor Problem: - There is no example showig how to print state names using a visitor. - There is no easy support to print sub State Machines state names. Solution: - Add example to print state names using a custom visitor and a composite State Machine. --- example/CMakeLists.txt | 2 + example/visitor.cpp | 84 +++++++++++++++++++++ include/boost/sml.hpp | 8 +- include/boost/sml/aux_/utility.hpp | 2 +- include/boost/sml/back/policies/testing.hpp | 1 - include/boost/sml/transition_table.hpp | 6 +- 6 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 example/visitor.cpp diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 51456462..3eb35489 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -84,4 +84,6 @@ if (IS_COMPILER_GCC_LIKE) add_example(testing example_testing testing.cpp) add_example(transitions example_transitions transitions.cpp) + + add_example(visitor example_visitor visitor.cpp) endif() diff --git a/example/visitor.cpp b/example/visitor.cpp new file mode 100644 index 00000000..050cf5ed --- /dev/null +++ b/example/visitor.cpp @@ -0,0 +1,84 @@ +// +// Copyright (c) 2016-2020 Kris Jusiak (kris at jusiak dot net) +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include +#include +#include + +namespace sml = boost::sml; + +struct e1 {}; +struct e2 {}; +struct e3 {}; +struct e4 {}; +struct e5 {}; + +struct sub { + auto operator()() const { + using namespace sml; + // clang-format off + return make_transition_table( + *"idle"_s + event = "sub1"_s + , "sub1"_s + event = X + ); + // clang-format on + } +}; + +struct composite { + auto operator()() const { + using namespace sml; + // clang-format off + return make_transition_table( + *"idle"_s + event = "s1"_s + , "s1"_s + event = state + , state + event = X + ); + // clang-format on + } +}; + +template +class state_name_visitor { + public: + explicit state_name_visitor(const TSM& sm) : sm_{sm} {} + + template + void operator()(boost::sml::aux::string>) const { + std::cout << boost::sml::aux::get_type_name() << ':'; + sm_.template visit_current_states>(*this); + } + + template + void operator()(TState state) const { + std::cout << state.c_str() << '\n'; + } + + private: + const TSM& sm_; +}; + +int main() { + sml::sm sm{}; + + const auto state_name = state_name_visitor{sm}; + + sm.process_event(e1{}); + sm.visit_current_states(state_name); // s1 + + sm.process_event(e2{}); + sm.visit_current_states(state_name); // sub:idle + + sm.process_event(e3{}); + sm.visit_current_states(state_name); // sub:sub1 + + sm.process_event(e4{}); + sm.visit_current_states(state_name); // sub:terminate + + sm.process_event(e5{}); + sm.visit_current_states(state_name); // terminate +} diff --git a/include/boost/sml.hpp b/include/boost/sml.hpp index e998d86d..9ca63b88 100644 --- a/include/boost/sml.hpp +++ b/include/boost/sml.hpp @@ -338,7 +338,7 @@ struct missing_ctor_parameter { operator U() { return {}; } -#if !defined(_MSC_VER) && !defined(__clang__) +#if !(defined(_MSC_VER) && !defined(__clang__)) template ::value)> operator TMissing &() const { static_assert(missing_ctor_parameter::value, @@ -2589,7 +2589,7 @@ struct transition, state, front::event, always, none> { }; } using _ = back::_; -#if !defined(_MSC_VER) && !defined(__clang__) +#if !(defined(_MSC_VER) && !defined(__clang__)) template constexpr front::event event{}; #else @@ -2606,7 +2606,7 @@ template front::event> exception __BOOST_SML_VT_INIT; using anonymous = back::anonymous; using initial = back::initial; -#if !defined(_MSC_VER) && !defined(__clang__) +#if !(defined(_MSC_VER) && !defined(__clang__)) template constexpr typename front::state_sm::type state{}; #else @@ -2614,7 +2614,7 @@ template typename front::state_sm::type state __BOOST_SML_VT_INIT; #endif inline namespace literals { -#if !defined(_MSC_VER) && !defined(__clang__) +#if !(defined(_MSC_VER) && !defined(__clang__)) template constexpr auto operator""_s() { return front::state>{}; diff --git a/include/boost/sml/aux_/utility.hpp b/include/boost/sml/aux_/utility.hpp index 4166bbc8..1dbd24ec 100644 --- a/include/boost/sml/aux_/utility.hpp +++ b/include/boost/sml/aux_/utility.hpp @@ -160,7 +160,7 @@ struct missing_ctor_parameter { return {}; } -#if !defined(_MSC_VER) && !defined(__clang__) // __pph__ +#if !(defined(_MSC_VER) && !defined(__clang__)) // __pph__ template ::value)> operator TMissing &() const { static_assert(missing_ctor_parameter::value, diff --git a/include/boost/sml/back/policies/testing.hpp b/include/boost/sml/back/policies/testing.hpp index 5e50defc..057aacd2 100644 --- a/include/boost/sml/back/policies/testing.hpp +++ b/include/boost/sml/back/policies/testing.hpp @@ -13,7 +13,6 @@ namespace back { namespace policies { struct testing_policy__ {}; - struct testing : aux::pair {}; } // namespace policies diff --git a/include/boost/sml/transition_table.hpp b/include/boost/sml/transition_table.hpp index 91eefc38..3710ad75 100644 --- a/include/boost/sml/transition_table.hpp +++ b/include/boost/sml/transition_table.hpp @@ -21,7 +21,7 @@ using _ = back::_; /// events -#if !defined(_MSC_VER) && !defined(__clang__) // __pph__ +#if !(defined(_MSC_VER) && !defined(__clang__)) // __pph__ template constexpr front::event event{}; #else // __pph__ @@ -46,7 +46,7 @@ using initial = back::initial; /// states -#if !defined(_MSC_VER) && !defined(__clang__) // __pph__ +#if !(defined(_MSC_VER) && !defined(__clang__)) // __pph__ template constexpr typename front::state_sm::type state{}; #else // __pph__ @@ -55,7 +55,7 @@ typename front::state_sm::type state __BOOST_SML_VT_INIT; #endif // __pph__ inline namespace literals { -#if !defined(_MSC_VER) && !defined(__clang__) // __pph__ +#if !(defined(_MSC_VER) && !defined(__clang__)) // __pph__ template constexpr auto operator""_s() { return front::state>{};