Hi Christophe, [snip]
1. Is there a way to access an attribute of an (original) event if the transition-table uses the "kleene" event?
Yes. As the doc states, a kleene event is a boost::any. You can use what boost::any offers. type(), which is used as an example, is a member of boost::any. The restriction is that you need to ask boost::any for a concrete type to get it back.
2. If there is a way, can I access it directly from the guard or actions-list in the transition-table?
Sure. For example:
BOOST_MSM_EUML_ACTION(pause_playback) { template
void operator()(EVT const& evt,FSM&,SourceState& ,TargetState& ) { cout << "player::pause_playback" << endl; std::cout << "event type: " << typeid(EVT).name() << std::endl; std::cout << "pause_playback with any event: " << evt.type().name() << std::endl; } }; The event is the EVT parameter, behind is hiding your kleene, and with it a boost::any. But I suspect it won't be enough for you, see below for more.
You are right. That it is not exactly, what I had in mind. Especially, with my second question I meant, if it might be possible to access the event's attribute directly from the guard or action list without writing an extra action for it (as I showed in my example or) as in the following example: // The transitions with kleene-event failing. // Only the second transition works/compiles. BOOST_MSM_EUML_TRANSITION_TABLE(( State1 + kleene [event_(EventNo) > Int_<7>()] == State2, State1 + event1 / (fsm_(lastEventNo) = event_(EventNo)) == State3 State2 + kleene / (fsm_(lastEventNo) = event_(EventNo)) == State3 ), stt)
3. If there is not a way, is it planned to be implemented (if possible) and when?
[snip]
// The FSM front-end and back-end: BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( stt, init_ << init_all_events ), FsmFrontend; typedef msm::back::state_machine<FsmFrontend> Fsm;
However, the expression "event_(EventNo)" in the transition-guard fails to compile with the following error:
error: no match for call to ‘(boost::msm::front::euml::GetEvent_
) (const boost::msm::front::euml::kleene_&, boost::msm::back::state_machine< boost::msm::front::euml::func_state_machine I read in the documentation of the Functor front-end that I should use boost::any::type() to access the original event in transition actions, but I do not really know how to go on with it. I am also not sure if this applies to the eUML front-end at all (especially in the transition-guard).
Ah this is already becoming more "fun" :) No, you don't have to use type(), it was just an example. With the known limitations of boost::any, all you can do is call any's any_cast on your event, check if it is one of your eventXXX, then you have the original event and you can call its members. It's not particularly beautiful but it's all what boost officially has to offer.
Note that I insist on "officially". Let's suppose you'd have a look on the excellent, accepted but not in any boost release, type_erasure, now the situation looks better.
That is a funny coincidence. On the same evening after I wrote you my first email I heard a talk about Boost.TypeErasure. :-) Quite interesting library.
Disclaimer: this was not documented because I hadn't tried it out yet. I just tried now quickly because I suspect you'll need it but there might be some bugs. This being said, please attach your seat belt, it might get bumpy :)
You can define your type_erasure's any with extra members and use them in your guards and actions.
BOOST_TYPE_ERASURE_MEMBER((has_getNumber), getNumber, 0); //type erasure event typedef ::boost::mpl::vector< has_getNumber
, boost::type_erasure::relaxed_match, boost::type_erasure::copy_constructible<>, boost::type_erasure::typeid_<> any_number_event_concept; struct any_number_event : boost::type_erasure::any
, msm::front::euml::euml_event
{ template <class U> any_number_event(U const& u): boost::type_erasure::any (u){} any_number_event(): boost::type_erasure::any (){} }; All you still need to do is tell MSM about your own, brand new kleene event as explained here: http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch03s03.html#any-even...
namespace boost { namespace msm{ template<> struct is_kleene_event< any_number_event > { typedef boost::mpl::true_ type; }; }}
[snip]
Granted, this is already quite advanced but AFAIK there is no other way.
There is however a catch: I don't know if all this is possible with the full eUML as you use it. I'm afraid you'll have to do as in my example and go for the almost eUML (no event attributes, classical events).
You seem to be right. I tried a long time to get this to work with the
any_event getting a method "get_attribute" (which "event_(attribute)"
seems to call). However, the compiler complains about being unable to do
proper type-deduction. But maybe, it is possible, but needs a more
experiences meta-template-programmer than me. :-)
However, I created some helper-Macros (almost identical to your
"BOOST_MSM_EUML_EVENT" and "BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES"
macros), and some helper actions (similar to your "Int_" action) which
allow me to create and access the (event-number) attributes almost as I
tried before.
Here they are:
// Macro which is identical to BOOST_MSM_EUML_EVENT but with
// additional parameter "members_list" which are all additional
// members surrounded by one pair of parentheses.
// The members from "members_list" will be inserted verbatim!
#define MY_BOOST_MSM_EUML_EVENT_WITH_MEMBERS(instance_name, \
members_list) \
struct instance_name ## _helper : \
msm::front::euml::euml_event