如何在SML状态或状态机中添加/初始化成员?

问题描述 投票:0回答:1

我使用 boost::sml

设计了这个状态机
struct LooperStateMachine {
    auto operator()() const {
        using namespace sml;
        
        return make_transition_table(
                *"beggining"_s + event<heel> / onRecordFirstLoop.value() = "recording_first_loop"_s,
                "recording_first_loop"_s + event<heel>[is_heel_valid] / onRecordLoops.value() = "recording_other_loops_and_playing"_s,
                "recording_first_loop"_s + event<toe>[is_toe_valid] / onPlayLoops.value() = "playing_loops"_s,
                "playing_loops"_s + event<toe>[is_toe_valid]/onStopPlayingLoops.value() = "stopped"_s,
                "playing_loops"_s + event<heel>[is_heel_valid]/onRecordLoops.value() = "recording_other_loops_and_playing"_s,
                "recording_other_loops_and_playing"_s + event<toe>[is_toe_valid] / onPlayLoops.value() = "playing_loops"_s,
                "stopped"_s + event<toe>[is_toe_valid] / onClearLoops.value() = "beggining"_s,
                "stopped"_s + event<heel>[is_heel_valid] / onSaveLoops.value() = "stopped"_s
        );
        
    }

    std::optional<std::function<void()>> onClearLoops;
    std::optional<std::function<void()>> onSaveLoops;
    std::optional<std::function<void()>> onPlayLoops;
    std::optional<std::function<void()>> onRecordLoops;
    std::optional<std::function<void()>> onRecordFirstLoop;
    std::optional<std::function<void()>> onStopPlayingLoops;
};

但是,要使用它,

sm
自动实例化它:

int main() {
    using namespace sml;

    sm<LooperStateMachine> sm;
    

所以我没有机会设置我的功能。

如何设置功能?

c++ c++17 boost-sml
1个回答
3
投票

对于你的literal问题,你可能只提供一个默认的构造函数/NSMI。不过,我知道您希望能够“动态”切换这些操作“挂钩”。

关于注入函数钩子,文档say

SML 状态不能有数据,因为数据被直接注入到守卫/动作中

这给了我将 runtime 状态与状态机分离的想法:

旁白:可选函数是多余的,

function<>
已经可以是无值的,并且可以方便地转换为 bool fdr,就像
optional<>
一样。

在 Wandbox 上直播

#include <boost/sml.hpp>
#include <functional>
#include <iostream>
namespace sml = boost::sml;

namespace looping {
    struct heel { };
    struct toe { };
    static auto is_heel_valid = []() { return false; };
    static auto is_toe_valid = []() { return false; };

    using DynamicAction = std::function<void()>;
    struct Hooks {
        DynamicAction onClearLoops;
        DynamicAction onSaveLoops;
        DynamicAction onPlayLoops;
        DynamicAction onRecordLoops;
        DynamicAction onRecordFirstLoop;
        DynamicAction onStopPlayingLoops;
    };

    static auto onClearLoops       = [](Hooks &hooks) { if (hooks.onClearLoops)       hooks.onClearLoops();       };
    static auto onSaveLoops        = [](Hooks &hooks) { if (hooks.onSaveLoops)        hooks.onSaveLoops();        };
    static auto onPlayLoops        = [](Hooks &hooks) { if (hooks.onPlayLoops)        hooks.onPlayLoops();        };
    static auto onRecordLoops      = [](Hooks &hooks) { if (hooks.onRecordLoops)      hooks.onRecordLoops();      };
    static auto onRecordFirstLoop  = [](Hooks &hooks) { if (hooks.onRecordFirstLoop)  hooks.onRecordFirstLoop();  };
    static auto onStopPlayingLoops = [](Hooks &hooks) { if (hooks.onStopPlayingLoops) hooks.onStopPlayingLoops(); };

    struct LooperStateMachine {
        auto operator()() const {
            using namespace sml;
            
            return make_transition_table(
                *"beginning"_s + event<heel> / onRecordFirstLoop = "recording_first_loop"_s,
                "recording_first_loop"_s + event<heel>[is_heel_valid] / onRecordLoops = "recording_other_loops_and_playing"_s,
                "recording_first_loop"_s + event<toe>[is_toe_valid] / onPlayLoops = "playing_loops"_s,
                "playing_loops"_s + event<toe>[is_toe_valid]/onStopPlayingLoops = "stopped"_s,
                "playing_loops"_s + event<heel>[is_heel_valid]/onRecordLoops = "recording_other_loops_and_playing"_s,
                "recording_other_loops_and_playing"_s + event<toe>[is_toe_valid] / onPlayLoops = "playing_loops"_s,
                "stopped"_s + event<toe>[is_toe_valid] / onClearLoops = "beginning"_s,
                "stopped"_s + event<heel>[is_heel_valid] / onSaveLoops = "stopped"_s
            );
        }
    };
}

int main() {
    looping::Hooks hooks;
    hooks.onClearLoops = [] { std::cout << "Clearing them\n"; };

    sml::sm<looping::LooperStateMachine> sm(hooks);
}

免责声明:我对这个库只有最薄弱的了解。我发现它是一个令人费解的东西,但以一种越来越积极的方式来处理。

© www.soinside.com 2019 - 2024. All rights reserved.