#c #boost #boost-msm #boost-mp11
Вопрос:
boost::mp11::mp_list
Может ли использоваться вместо списка boost::mpl::vector
переходов в машинах состояний, построенных с boost::msm
помощью ?
Я только что попробовал (ссылка), и кажется, что:
- он компилирует
- но это не работает — таблицы переходов отсутствуют
- и производит 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
проблеме.