【问题标题】:How to reset boost::sml::sm instance如何重置 boost::sml::sm 实例
【发布时间】:2018-06-20 06:40:26
【问题描述】:

boost::sml::sm 似乎没有任何特定的重置方法,并且它缺少移动赋值运算符,因此我无法执行诸如分配新实例之类的操作(例如 machine = boost::sml::sm<MyMachine>{})。我目前的方法是调用 dtor 和 ctor 的丑陋技巧:

machine.~sm();
new (&machine) std::decay_t<decltype(machine)>();

有没有更好的办法?

【问题讨论】:

    标签: c++ boost state-machine


    【解决方案1】:

    像往常一样做(即永远不要写你实际写的东西):使用包装器来管理生命周期,例如使用optionalunique_ptr

    例子:

    Live On Coliru

    //
    // Copyright (c) 2016-2018 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 <boost/sml.hpp>
    #include <cassert>
    
    namespace sml = boost::sml;
    
    namespace {
    // events
    struct release {};
    struct ack {};
    struct fin {};
    struct timeout {};
    
    // guards
    const auto is_ack_valid = [](const ack&) { return true; };
    const auto is_fin_valid = [](const fin&) { return true; };
    
    // actions
    const auto send_fin = [] {};
    const auto send_ack = [] {};
    
    struct hello_world {
      auto operator()() const {
        using namespace sml;
        // clang-format off
        return make_transition_table(
          *"established"_s + event<release> / send_fin = "fin wait 1"_s,
           "fin wait 1"_s + event<ack> [ is_ack_valid ] = "fin wait 2"_s,
           "fin wait 2"_s + event<fin> [ is_fin_valid ] / send_ack = "timed wait"_s,
           "timed wait"_s + event<timeout> / send_ack = X
        );
        // clang-format on
      }
    };
    }
    
    #include <boost/optional.hpp>
    #include <iostream>
    int main() {
      using namespace sml;
    
      boost::optional<sm<hello_world> > m;
    
      static_assert(2 == sizeof(m), "sizeof(m) != 2b");
    
      auto run = [&] {
          assert(m->is("established"_s));
    
          m->process_event(release{});
          assert(m->is("fin wait 1"_s));
    
          m->process_event(ack{});
          assert(m->is("fin wait 2"_s));
    
          m->process_event(fin{});
          assert(m->is("timed wait"_s));
    
          m->process_event(timeout{});
          assert(m->is(X));  // released
      };
    
      for (auto i : {1,2,3}) {
          std::cout << "Run " << i << "\n";
          m.emplace(); // default constructs a sm in-place
          run();
      }
    }
    

    打印

    Run 1
    Run 2
    Run 3
    

    【讨论】:

    • 现在采样Live
    • 谢谢。下次我会帮忙的。 (提示:我没有说 unique_ptr 没有开销,optional“更改语义”是否值得商榷。我想只需在 Boost Sml 库中提交功能请求即可。)
    • 附言。我只是指出任意限制需要您解决它们。您当然可以考虑自定义终身适配器并将其命名为reinitializable&lt;T&gt; 或其他名称。似乎这可能在您的食谱中:en.cppreference.com/w/cpp/utility/launder
    猜你喜欢
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 2021-11-06
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多