[Statechart] casting event type in unconsumed_event
Hi, Here some code: //snippet on template< class MostDerived > struct EventA : sc::event< MostDerived > { virtual std::string name() { return "unnamed event"; } }; struct EventB : public EventA< EventB > { std::string name() { return "EventB"; } }; struct MyMachine : sc::state_machine< MyMachine, Whatever > { void unconsumed_event( const sc::event_base & evt ) { // How can I display a message here with the event name? } }; //snippet off So the objective is to display the event name returned by the 'name' function when an event is unconsumed. I have tried some way like using dynamic_type and static_type but no luck... Any idea? Thank you. JD
Hi JD [snip rest of code]
struct MyMachine : sc::state_machine< MyMachine, Whatever > { void unconsumed_event( const sc::event_base & evt ) { // How can I display a message here with the event name? } };
There are two options to do this: 1) Use C++ RTTI, i.e. type_info::name(). This is the easiest option as it necessitates the least amount of work but of course requires that you compile your program with C++ RTTI enabled. 2) Use event_base::custom_static_type_ptr http://www.boost-consulting.com/boost/libs/statechart/doc/reference.html#eve... and event_base::custom_dynamic_type_ptr http://www.boost-consulting.com/boost/libs/statechart/doc/reference.html#eve... as demonstrated for states in http://www.boost-consulting.com/boost/libs/statechart/doc/tutorial.html#Stat.... This requires slightly more work than 1) but works even if you compile your program with C++ RTTI disabled.
So the objective is to display the event name returned by the 'name' function when an event is unconsumed. I have tried some way like using dynamic_type and static_type but no luck...
See above, that should solve the event name problem quite nicely. HTH, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
Andreas Huber wrote:
There are two options to do this: 1) Use C++ RTTI, i.e. type_info::name(). This is the easiest option as it necessitates the least amount of work but of course requires that you compile your program with C++ RTTI enabled. 2) Use event_base::custom_static_type_ptr
Andreas, Thanks for your quick answer. It works for this particular problem, but still I have a more general problem with Boost.Statechart that bother me. In the faq I read: Q. Does Boost.Statechart support polymorphic events? A. No. Although events can be derived from each other to write common code only once Ok but polymorphism is more than just factorizing code. The way an event has still to define a "MostDerived" template prevent from using an event as a generic object. Consider the same example given above: //snippet on template< class MostDerived > struct EventA : sc::event< MostDerived > { virtual std::string name() { return "unnamed event"; } }; struct EventB : public EventA< EventB > { std::string name() { return "EventB"; } }; struct EventC : public EventA< EventC > { std::string name() { return "EventC"; } }; //snippet off Now, how can I have a function that create events following an argument. For example I read patterns in file, and following the pattern I found, I have to create different event: //snippet on getline(is, line); theGenericEvent = the_function_in_question(line); MyMachine.post_event(theGenericEvent); //snippet off I simply can't do that. Or I'm missing something. What is the rational for events not supporting polymorphism? Thanks in advance for your time. JD
JD wrote:
Thanks for your quick answer. It works for this particular problem, but still I have a more general problem with Boost.Statechart that bother me. In the faq I read:
Q. Does Boost.Statechart support polymorphic events? A. No. Although events can be derived from each other to write common code only once
Ok but polymorphism is more than just factorizing code.
In my experience with events you rarely need true polymorphism. If you do, you can often use the trick demonstrated in the FAQ item you refer to. True, from a purely functional perspective this is a limitation I'd rather not have in the library. However, this limitation makes the implementation of the internally used RTTI mechanism much easier and much faster.
The way an event has still to define a "MostDerived" template prevent from using an event as a generic object.
It depends. It is true that there is currently no way to use a common custom base class for events and states as long as you restrict yourself to single inheritance. That is, if event_base does not offer what you look for then you need to multi-inherit your events from your custom base and statechart::event<> and use cross casts to gain access to the custom base. This is demonstrated with events here: http://www.boost-consulting.com/boost/libs/statechart/doc/tutorial.html#Gett... (see the call to state_cast<>, which uses dynamic_cast under the hood) [snip]
//snippet on getline(is, line); theGenericEvent = the_function_in_question(line); MyMachine.post_event(theGenericEvent); //snippet off
I simply can't do that. Or I'm missing something. What is the rational for events not supporting polymorphism?
Have a look at the signature of post_event: http://www.boost-consulting.com/boost/libs/statechart/doc/reference.html#pos... What is stopping you to declare theGenericEvent variable above as event_base type? HTH, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
Andreas Huber wrote:
access to the custom base. This is demonstrated with events here:
I meant states instead of events.
What is stopping you to declare theGenericEvent variable above as event_base type?
More precisely, why don't you call as follows: boost::intrusive_ptr<const event_base> theGenericEvent = the_function_in_question(line); -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
participants (2)
-
Andreas Huber
-
JD