C++ 可视化sml状态机

C++ 可视化sml状态机,c++,boost,C++,Boost,我第一次在boost sml中构建了一个更大的状态机,需要一种可视化(例如,导出到graphviz)整个状态机的方法。你知道怎么做吗?有没有办法迭代状态机的结构并打印出来 免责声明:我对SML没有任何经验(必须找到它的位置) 第一次尝试,嗯 然而,尝试使用visit\u current\u states界面做一些事情,我想到了这个。。。在给定事件列表的情况下,映射出(复合)状态机的实现不是很好: #include <boost/sml.hpp> namespace sml = bo

我第一次在boost sml中构建了一个更大的状态机,需要一种可视化(例如,导出到graphviz)整个状态机的方法。你知道怎么做吗?有没有办法迭代状态机的结构并打印出来

免责声明:我对SML没有任何经验(必须找到它的位置)

第一次尝试,嗯 然而,尝试使用
visit\u current\u states
界面做一些事情,我想到了这个。。。在给定事件列表的情况下,映射出(复合)状态机的实现不是很好:

#include <boost/sml.hpp>

namespace sml = boost::sml;
namespace aux = sml::aux;

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<e3> = "sub1"_s
            , "sub1"_s + event<e4> = X
        );
        // clang-format on
    }
};

struct composite {
    auto operator()() const {
        using namespace sml;
        // clang-format off
        return make_transition_table(
             *"idle"_s   + event<e1> = "s1"_s
            , "s1"_s     + event<e2> = state<sub>
            , state<sub> + event<e5> = X
        );
        // clang-format on
    }
};

#include <boost/hana.hpp>
#include <boost/core/demangle.hpp>
#include <iostream>
#include <iomanip>

namespace mapper {
    namespace hana = boost::hana;
    using namespace std::string_literals;
    using boost::core::demangle;
    
    template <typename F> struct ycombine {
        ycombine(F f):f(f) {}
        F f;
        template <typename... A>
        auto operator()(A... a) const { return f(*this, a...); };
    };

    hana::tuple<e1,e2,e3,e4,e5> events;

    template <class TSM> class Vis {
      public:
        explicit Vis(const TSM& sm, std::string prefix = "") : sm_{ sm }, prefix(prefix) {}

        template <class TSub>
        void operator()(aux::string<boost::sml::sm<TSub>>) const {
            auto subname = aux::get_type_name<TSub>();

            Vis nvis(sm_, prefix + '/' + subname);
            sm_.template visit_current_states<aux::identity<TSub>>(nvis);
            prefix = nvis.prefix;
        }

        template <class TState> void operator()(TState state) const {
            prefix += "/"s + state.c_str();
        }

      private:
        const TSM& sm_;
      public:
        mutable std::string prefix;
    };

    template <typename SM>
    std::string get_current(SM const& sm) {
        Vis<SM> v{sm};
        sm.visit_current_states(v);
        return v.prefix;
    };
}

int main() {
    using namespace mapper;

    auto recurse = ycombine {
        [](auto self, auto sm) {
            hana::for_each(events, [=](auto ev) {
                auto clone = sm;
                auto from = get_current(clone);
                clone.process_event(ev);
                auto to = get_current(clone);

                if (from != to) {
                    std::cout
                        << std::quoted(from) << " -> "
                        << std::quoted(to) 
                        << " [label=" << std::quoted(demangle(typeid(ev).name())) << "]\n";

                    self(clone);
                }
            });
        } };

    std::cout << "digraph {\n";
    recurse(sml::sm<composite>{});
    std::cout << "}\n";
}
为了获得灵感,输出:

@startuml

[*] --> idle
idle --> s1 : e1
s1 --> s2 : e2 [guard] / action
s2 --> s1 : e3 [guard]
s2 --> terminate : e4 / action

@enduml
显然,不是graphviz,但实际上看起来更“可信”,因为

  • 它类似于某种标准的UML符号
  • 是由图书馆的作者写的吗
  • 包括我无法提供的细节(主要是因为不知道他们的存在/工作)


天哪,我怎么会忽略了垃圾场的例子:(该死……谢谢!我猜是这样的:)我印象深刻,你从没有看过SML就把它拔了出来。你是如何发现访问美国的?我已经看了3个星期的页面,今天才发现它,试图了解visitor.cpp示例中发生了什么。我想我对库源进行了一些关键字搜索,包括示例。就我所记得的,我在最后一个样本中匹配了它?虽然你仍然可以找到它,但这个例子似乎不是。似乎该示例仅被删除,提交消息确认其文档不足。我敢肯定,我刚刚在实际结账时使用了灰色,而我恰好是在添加了该样本一个月之后:)
@startuml

[*] --> idle
idle --> s1 : e1
s1 --> s2 : e2 [guard] / action
s2 --> s1 : e3 [guard]
s2 --> terminate : e4 / action

@enduml