This is my first post to the list. I've been working with MSM and have been pulling my hair out over what I now think is a bug, either in the library or the compiler.
If you create an action, and inside that action you do a get_attribute on the state machine, and that state machine (MSM) is a sub-statemachine of another (parent) MSM, and that sub-machine state happens to be the initial state of the parent machine (that's a lot of ifs!), the code will not compile. It aborts with the mysterious error:
c:\boost_1_51_0\boost\fusion\container\map\detail\deref_data_impl.hpp(28): error C2039: 'second_type' : is not a member of 'boost::mpl::void_'
followed by the traditional slew of other stuff.
Although this example is easy enough to work around, I've found whether it works or not is erratic. The one thing that seems to work OK is to move the action out of the entry for the sub machine and into the entry of the first state, but I haven't done enough testing to show that this works.
I've attached a zip and included the text of a sample. As is it will not compile. You can either uncomment the attribute assignment or change the initial state to make it compile.
Any help with this would be appreciated! Thanks!
-Chiem
Here's sample code. I've also attached a zip:
#include <vector>
#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/euml/euml.hpp>
using namespace std;
using namespace boost::msm::front::euml;
namespace msm = boost::msm;
namespace MSM_A // Concrete FSM implementation
{
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int, borrowedBuffer_attribute);
BOOST_MSM_EUML_ACTION(someAction)
{
template <class Event,class FSM,class STATE>
void operator()(Event const& event,FSM& fsm, STATE&)
{
fsm.get_attribute(borrowedBuffer_attribute)=1; // <--------------- UNCOMMENTING THIS WILL ALSO ALLOW COMPILATION
}
};
BOOST_MSM_EUML_EVENT(someevent)
BOOST_MSM_EUML_STATE((no_action), someStateA)
BOOST_MSM_EUML_STATE((no_action), someStateB)
BOOST_MSM_EUML_TRANSITION_TABLE((
someStateA + someevent == someStateB
),transition_table)
BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table,
init_ << someStateA,
someAction, // <-------------------- ACTION IS AN ENTRY ACTION
no_action,
attributes_ << borrowedBuffer_attribute,
configure_ << no_configure_
),
MSM_A_frontEnd) //fsm name
typedef msm::back::state_machine<MSM_A_frontEnd> MSM_A_player;
}
namespace MSM_B // Concrete FSM implementation
{
::MSM_A::MSM_A_player subMachine;
BOOST_MSM_EUML_EVENT(someEvent)
BOOST_MSM_EUML_STATE((no_action), someState)
BOOST_MSM_EUML_TRANSITION_TABLE((
someState + someEvent == subMachine
), transition_table)
BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
//init_ << someState, // <---------------- WORKS
init_ << subMachine, // <---------------- DOES NOT COMPILE
no_action, // Entry
no_action, // Exit
attributes_ << no_attributes_, // Attributes
configure_ << no_configure_
),
MSM_B_frontEnd) //fsm name
typedef msm::back::state_machine<MSM_B_frontEnd> MSM_B_player;
}
int main()
{
MSM_B::MSM_B_player player;
player.start();
return 0;
}