boost::mp11::mp_list 无法根据 boost::msm 为 FSM 定义正确的转换 table,缺少什么?

boost::mp11::mp_list can't define proper transition table for FSM based on boost::msm, what is missing?

是否可以使用 boost::mp11::mp_list 代替 boost::mpl::vector 作为由 boost::msm 构造的状态机中的转换列表?

我刚试了一下 (link) 好像是:

  1. 它编译
  2. 但它不起作用 - 缺少转换表
  3. boost::mpl::vector.
  4. 相比,产生 1/3 的代码

我也试过 boost::fusion::vector 并且有效。

我做了什么:

我简化了 boost::msm 中的示例 - see - 只是为了有 2 个状态和 2 个转换。

我将所有 mpl::vector 替换为 TypeList 定义为:

#ifdef USE_FUSION

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/include/mpl.hpp>

template <typename ...T>
using TypeList = boost::fusion::vector<T...>;

#elif USE_MP11

#include <boost/mp11/list.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/mpl.hpp>


template <typename ...T>
using TypeList = boost::mp11::mp_list<T...>;

#else

template <typename ...T>
using TypeList = boost::mpl::vector<T...>;

#endif

状态机如下:

namespace msm = boost::msm;

namespace test_fsm // Concrete FSM implementation
{
// events
struct play {};
struct stop {};

// Concrete FSM implementation 
struct player_ : public msm::front::state_machine_def<player_>
{
    // no need for exception handling or message queue
    typedef int no_exception_thrown;
    typedef int no_message_queue;

    // The list of FSM states
    struct Empty : public msm::front::state<> 
    {
        // optional entry/exit methods
        template <class Event,class FSM>
        void on_entry(Event const&,FSM& ) { std::cout << "entering: Empty" << std::endl; }
        template <class Event,class FSM>
        void on_exit(Event const&,FSM& ) { std::cout << "leaving: Empty" << std::endl; }
    };

    struct Playing : public msm::front::state<>
    {
        template <class Event,class FSM>
        void on_entry(Event const&,FSM& ) { std::cout << "entering: Playing" << std::endl; }
        template <class Event,class FSM>
        void on_exit(Event const&,FSM& ) { std::cout << "leaving: Playing" << std::endl; }
    };

    // the initial state of the player SM. Must be defined
    typedef Empty initial_state;
    // transition actions
    void playing(play const&)  {  }
    void stop_playing(stop const&)  {  }
    
    // guard conditions

    typedef player_ p; // makes transition table cleaner

    // Transition table for player
    struct transition_table : TypeList<
        //    Start     Event         Next      Action                 Guard
        //    +---------+-------------+---------+---------------------+----------------------+
            _row < Empty , play        , Playing       >,
            _row < Playing , stop        , Empty       >
    > {};

    // Replaces the default no-transition response.
    template <class FSM,class Event>
    void no_transition(Event const& e, FSM&,int state)
    {
        std::cout << "no transition from state " << state
            << " on event " << typeid(e).name() << std::endl;
    }
};
typedef msm::back::state_machine<player_> player;

//
// Testing utilities.
//
static char const* const state_names[] = { "Empty", "Playing" };

void pstate(player const& p)
{
    std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
}

}

对于这个简单的场景:

test_fsm::player p2;
p2.start();
p2.process_event(test_fsm::play());
p2.process_event(test_fsm::stop()); 
return 0;

基于 boost::mpl::vector(以及 boost::fusion::vectorboost::mpl::list)的示例产生了预期的输出:

entering: Empty 
leaving: Empty 
entering: Playing 
leaving: Playing
entering: Empty

在使用 boost::mp11::mp_list 时输出:

entering: Empty
no transition from state 0 on event N8test_fsm4playE
no transition from state 0 on event N8test_fsm4stopE

您是否知道使用 boost::mp11 缺少什么,或者目前无法使用 boost::mp11::mp_list 作为 boost::msm 状态的转换表?

似乎使用 boost::mp11::mp_list 作为 boost::msm 中的过渡行列表的唯一方法是使用 typedef(使用)——继承不起作用;所需的更改为 follows:


    // Transition table for player
    using transition_table = boost::mp11::mp_list<
            _row < Empty , play        , Playing       >,
            _row < Playing , stop        , Empty       >
    >;

接下来的观察是这个版本,带有类型别名,也适用于其他类型:boost::mpl::vectorboost::fusion::vector

我想,在所有 boost::msm 示例中使用继承(而不是类型别名)来定义转换表,可能是由于缩短了模板实例化名称的长度(不确定)。

嗯,反正我是举报了 boost::mp11 issue.