I just wanted to modernize my code - and try to use boost::mp11::mp_list
instead of boost::mpl::vector
in my FSM definitions.
Simplified code is as follows:
#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/mpl.hpp>
namespace msm = boost::msm;
namespace test_fsm
{
struct play {};
struct stop {};
struct player_ : public msm::front::state_machine_def<player_>
{
typedef int no_exception_thrown;
typedef int no_message_queue;
struct Empty : public msm::front::state<>
{
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; }
};
typedef Empty initial_state;
// transition actions
void playing(play const&) { }
void stop_playing(stop const&) { }
typedef player_ p;
struct transition_table : boost::mp11::mp_list<
_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;
}
};
}
int main()
{
test_fsm::player p2;
p2.start();
p2.process_event(test_fsm::play());
p2.process_event(test_fsm::stop());
return 0;
}
It compiles, but produces unexpected output:
entering: Empty
no transition from state 0 on event N8test_fsm4playE
no transition from state 0 on event N8test_fsm4stopE
While - with original version (just replacing mp11::mp_list with mpl::vector) it works as expected:
entering: Empty
leaving: Empty
entering: Playing
leaving: Playing
entering: Empty
It also works as expected with boost::fusion::vector
.
I found one workaround - when using type-alias for defining transition table it works as expected:
using transition_table = boost::mp11::mp_list<
_row < Empty , play , Playing >,
_row < Playing , stop , Empty >
> ;
With type-alias it also works for other types boost::mpl::vector and boost::fustion::vector.
I am not sure what this inheritance is for, but all examples from boost::msm defines this transition tables that way.
The problem with boost::mp11::mp_list
is probably here <boost/mp11/mpl.hpp> - but I am not sure that.
I asked the question about that on SO: https://stackoverflow.com/questions/68195912/boostmp11mp-list-cant-define-proper-transition-table-for-fsm-based-on-boost - but not get much attention.
You can play with the problem on compiler explorer: https://godbolt.org/z/jTEnxPMTj
The problem is not related to version of boost or compiler.