boost-ext / sml

C++14 State Machine library
https://boost-ext.github.io/sml
Boost Software License 1.0
1.1k stars 173 forks source link

how to know weather state is a sub-state machine or a normal state #604

Open magni-mar opened 7 months ago

magni-mar commented 7 months ago

Here is a minimal sample which one can work from to answer my question:

#include <boost/asio.hpp>
#include <boost/sml.hpp>
#include <iostream>

struct running {
  static constexpr std::string_view name{ "running" };
};
struct not_running {
  static constexpr std::string_view name{ "not_running" };
};

struct state_machine {
  auto operator()() {
    using boost::sml::event;
    using boost::sml::operator""_s;

    auto table =
        boost::sml::make_transition_table(*"on"_s + event<running> = "off"_s, "off"_s + event<not_running> = "on"_s);
    return table;
  }
};

struct control_modes {
  auto operator()() {
    using boost::sml::event;
    using boost::sml::state;
    using boost::sml::operator""_s;

    auto table = boost::sml::make_transition_table(*"not_running"_s + event<running> = state<state_machine>,
                                                   state<state_machine> + event<running> = "running"_s);
    return table;
  }
};

auto main(int argc, char** argv) -> int {
  using boost::sml::state;
  using boost::sml::operator""_s;

  using state_machine_t = boost::sml::sm<control_modes, state_machine>;
  std::shared_ptr<state_machine_t> const sm{ std::make_shared<state_machine_t>(control_modes{}, state_machine{}) };

  // "not_running"_s and state<state_machine>
  auto s1 = "not_running"_s;
  auto s2 = state<state_machine>;

  std::cout << "sm: " << sm->is(s1) << std::endl;
  std::cout << "sm: " << sm->is(s2) << std::endl;

  sm->process_event(running{});

  std::cout << "sm: " << sm->is(s1) << std::endl;
  std::cout << "sm: " << sm->is(s2) << std::endl;
}

So I have been looking for a way to determine weather a state is a sub-state machine or not. So far, I have not found a way. In essence, in the above code I want a way to determine weather the outer state machine is currently in a state represented by the inner state machine. So I am looking for some way to be able to do the following:

  std::cout << s1.is_normal_state() << std::endl;
  std::cout << s2.is_sub_state_machine() << std::endl;
cmigliorini commented 3 months ago

If you have, say

Then you can determine substates as follows

// in B/on
bool b_on = sm.is<decltype(sml::state<B>)>(sml::state<on>);
// in B/off
bool b_off = sm.is<decltype(sml::state<B>)>(sml::state<off>);
// C/cold
bool b_cold = sm.is<decltype(sml::state<C>)>(sml::state<cold>);
// ...

Never tried this, though:

bool a_cold = sm.is<decltype(sml::state<A>)>(sml::state<cold>);