boost::mp11::mp_list не может определить правильную таблицу переходов для FSM на основе boost::msm, чего не хватает?

#c #boost #boost-msm #boost-mp11

Вопрос:

boost::mp11::mp_list Может ли использоваться вместо списка boost::mpl::vector переходов в машинах состояний, построенных с boost::msm помощью ?

Я только что попробовал (ссылка), и кажется, что:

  1. он компилирует
  2. но это не работает — таблицы переходов отсутствуют
  3. и производит 1/3 кода по сравнению с boost::mpl::vector .

Я тоже пытался boost::fusion::vector , и это работает.

Что я сделал:

Я упростил пример из boost::msm см. — просто чтобы иметь 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 constamp;,FSMamp; ) { std::cout << "entering: Empty" << std::endl; }
        template <class Event,class FSM>
        void on_exit(Event constamp;,FSMamp; ) { std::cout << "leaving: Empty" << std::endl; }
    };

    struct Playing : public msm::front::state<>
    {
        template <class Event,class FSM>
        void on_entry(Event constamp;,FSMamp; ) { std::cout << "entering: Playing" << std::endl; }
        template <class Event,class FSM>
        void on_exit(Event constamp;,FSMamp; ) { 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 constamp;)  {  }
    void stop_playing(stop constamp;)  {  }
    
    // 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 constamp; e, FSMamp;,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 constamp; 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::vector и boost::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 состояний?

Ответ №1:

Похоже, что единственный способ использовать boost::mp11::mp_list в качестве списка строк перехода boost::msm — использовать typedef (использование) — наследование не работает; необходимые изменения заключаются в следующем:

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

 

Следующее замечание состоит в том, что эта версия с псевдонимом типа работает также для других типов: boost::mpl::vector , boost::fusion::vector .

Я предполагаю, что использование наследования во всех boost::msm примерах (вместо псевдонима типа) для определения таблиц переходов, вероятно, обусловлено сокращением длины имен экземпляров шаблонов (не уверен в этом).

Ну, в любом случае, я сообщил об этом как о boost::mp11 проблеме.