
Hello, I have a question about Boost.Msm event conversion at exit pseudo state. (Version 1.47.0) http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch03s02.html#d0e942 Exit pseudo states struct event6 { event6(){} template <class Event> event6(Event const&){} }; //convertible from any event Above document said that we can convert the event using the template constructor. This exmaple doesn't access the constructor's parameter. I want to propagate some value of the event. Event2 is a source event. And Event3 is a target event like this.(see attached file) struct Event2 { Event2(int val_):val(val_) {} int val; }; struct Event3 { Event3(int val_):val(val_) {} template <class T> Event3(T const& e):val(e.val) {} // error Event3(Event2 const& e):val(e.val) {} // OK int val; }; // Transition table struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < SubState1, Event2, Exit, msmf::none, msmf::none > > {}; struct Exit :msm::front::exit_pseudo_state<Event3> {}; But compile error occurred. The compiler said Event1 doesn't have a member 'val'. I'm not sure why Event3's constructor instantiate from Event1. This is the question. If I define the constructor that has a parameter Event2 instead of template parameter, compile error doesn't occur. exit_pt_convert.cpp(attached file) is a source code that reproduces this error. Thanks, Takatoshi

Hello,
I have a question about Boost.Msm event conversion at exit pseudo state. (Version 1.47.0)
http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch03s02.html#d0e942
Exit pseudo states
struct event6 { event6(){} template <class Event> event6(Event const&){} }; //convertible from any event
Above document said that we can convert the event using the template constructor. This exmaple doesn't access the constructor's parameter.
I want to propagate some value of the event. Event2 is a source event. And Event3 is a target event like this.(see attached file)
struct Event2 { Event2(int val_):val(val_) {} int val; };
struct Event3 { Event3(int val_):val(val_) {} template <class T> Event3(T const& e):val(e.val) {} // error Event3(Event2 const& e):val(e.val) {} // OK int val; };
// Transition table struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < SubState1, Event2, Exit, msmf::none, msmf::none >
{};
struct Exit :msm::front::exit_pseudo_state<Event3> {};
But compile error occurred. The compiler said Event1 doesn't have a member 'val'. I'm not sure why Event3's constructor instantiate from Event1. This is the question. If I define the constructor that has a parameter Event2 instead of template parameter, compile error doesn't occur.
exit_pt_convert.cpp(attached file) is a source code that reproduces this error.
Thanks, Takatoshi Hi Takatoshi,
this question has already been asked some time ago in a slightly different context (http://lists.boost.org/Archives/boost/2010/09/170506.php). This is unfortunately one of the points where I had to leave the compile-time world earlier than I would like (but found no better solution yet). While Event1 will not be considered for forwarding, the compiler does not know because it's only known at run-time, and it therefore complains that you cannot create Event1 from Event2. The surprise to me is that the compiler is happy with only your second constructor, I'd expect it to require a constructor taking Event1. Should it happen, you will need to use the enable_if / disable_if workaround presented in the above thread. I'll update the doc so that this current limitation is documented until I find a better solution. Regards, Christophe

----- Original Message ----- From: "Christophe Henry" <christophe.j.henry@googlemail.com> Newsgroups: gmane.comp.lib.boost.devel To: <boost@lists.boost.org> Sent: Monday, October 10, 2011 9:54 PM Subject: Re: [msm]Event convert at exit point
Hello,
I have a question about Boost.Msm event conversion at exit pseudo state. (Version 1.47.0)
http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch03s02.html#d0e942
Exit pseudo states
struct event6 { event6(){} template <class Event> event6(Event const&){} }; //convertible from any event
Above document said that we can convert the event using the template constructor. This exmaple doesn't access the constructor's parameter.
I want to propagate some value of the event. Event2 is a source event. And Event3 is a target event like this.(see attached file)
struct Event2 { Event2(int val_):val(val_) {} int val; };
struct Event3 { Event3(int val_):val(val_) {} template <class T> Event3(T const& e):val(e.val) {} // error Event3(Event2 const& e):val(e.val) {} // OK int val; };
// Transition table struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < SubState1, Event2, Exit, msmf::none, msmf::none >
{};
struct Exit :msm::front::exit_pseudo_state<Event3> {};
But compile error occurred. The compiler said Event1 doesn't have a member 'val'. I'm not sure why Event3's constructor instantiate from Event1. This is the question. If I define the constructor that has a parameter Event2 instead of template parameter, compile error doesn't occur.
exit_pt_convert.cpp(attached file) is a source code that reproduces this error.
Thanks, Takatoshi Hi Takatoshi,
this question has already been asked some time ago in a slightly different context (http://lists.boost.org/Archives/boost/2010/09/170506.php). This is unfortunately one of the points where I had to leave the compile-time world earlier than I would like (but found no better solution yet). While Event1 will not be considered for forwarding, the compiler does not know because it's only known at run-time, and it therefore complains that you cannot create Event1 from Event2.
The surprise to me is that the compiler is happy with only your second constructor, I'd expect it to require a constructor taking Event1. Should it happen, you will need to use the enable_if / disable_if workaround presented in the above thread.
I'll update the doc so that this current limitation is documented until I find a better solution.
Regards,
Christophe
Or simplier: template <class T> Event3(T const& ):val(0) {} // not used Event3(Event2 const& e):val(e.val) {} //conversion constructor

Hi Christophe,
Hi Takatoshi,
this question has already been asked some time ago in a slightly different context (http://lists.boost.org/Archives/boost/2010/09/170506.php). This is unfortunately one of the points where I had to leave the compile-time world earlier than I would like (but found no better solution yet). While Event1 will not be considered for forwarding, the compiler does not know because it's only known at run-time, and it therefore complains that you cannot create Event1 from Event2.
The surprise to me is that the compiler is happy with only your second constructor, I'd expect it to require a constructor taking Event1. Should it happen, you will need to use the enable_if / disable_if workaround presented in the above thread.
I'll update the doc so that this current limitation is documented until I find a better solution.
Thanks for the reply. I understood current situation.
Or simplier:
template <class T> Event3(T const& ):val(0) {} // not used Event3(Event2 const& e):val(e.val) {} //conversion constructor
Correct. It works well. In my usecase, I think it's typical, the outer event(Event3) shouldn't know about inner event(Event2). In other words, outer event is an interface of a sub state machine. When I use the SFINAE solution, the predicate is important. If I choose the is_same, it still needs inner event information. template <class T> OuterEvent(T const& t, typename enable_if<is_same<T, InnerEvent> >::type* = 0); I considered some approaches. The first approach is the InnerEvent inherits the OuterEvent and use the is_base_of. struct InnerEvent:OuterEvent {}; is_base_of<T, OuterEvent> And next, I realized that if the InnerEvent inherits the OuterEvent, we can construct the OuterEvent from the InnerEvent automatically. It is the slicing. In my usecase, I think it works well. struct OuterEvent { int val; }; struct InnerEvent:OuterEvent {}; struct Exit:msm::front::exit_pseudo_state<OuterEvent> {}; // Start Event Next Action Guard msmf::Row < SubState1, InnerEvent, Exit, msmf::none, msmf::none > Regards, Takatoshi

----- Original Message ----- From: "Takatoshi Kondo" <redboltz@gmail.com> Newsgroups: gmane.comp.lib.boost.devel To: <boost@lists.boost.org> Sent: Wednesday, October 12, 2011 3:39 PM Subject: Re: [msm]Event convert at exit point
Hi Christophe,
Hi Takatoshi,
this question has already been asked some time ago in a slightly different context (http://lists.boost.org/Archives/boost/2010/09/170506.php). This is unfortunately one of the points where I had to leave the compile-time world earlier than I would like (but found no better solution yet). While Event1 will not be considered for forwarding, the compiler does not know because it's only known at run-time, and it therefore complains that you cannot create Event1 from Event2.
The surprise to me is that the compiler is happy with only your second constructor, I'd expect it to require a constructor taking Event1. Should it happen, you will need to use the enable_if / disable_if workaround presented in the above thread.
I'll update the doc so that this current limitation is documented until I find a better solution.
Thanks for the reply. I understood current situation.
Or simplier:
template <class T> Event3(T const& ):val(0) {} // not used Event3(Event2 const& e):val(e.val) {} //conversion constructor
Correct. It works well. In my usecase, I think it's typical, the outer event(Event3) shouldn't know about inner event(Event2). In other words, outer event is an interface of a sub state machine.
When I use the SFINAE solution, the predicate is important. If I choose the is_same, it still needs inner event information. template <class T> OuterEvent(T const& t, typename enable_if<is_same<T, InnerEvent> >::type* = 0);
I considered some approaches. The first approach is the InnerEvent inherits the OuterEvent and use the is_base_of.
struct InnerEvent:OuterEvent {}; is_base_of<T, OuterEvent>
And next, I realized that if the InnerEvent inherits the OuterEvent, we can construct the OuterEvent from the InnerEvent automatically. It is the slicing. In my usecase, I think it works well.
struct OuterEvent { int val; }; struct InnerEvent:OuterEvent {}; struct Exit:msm::front::exit_pseudo_state<OuterEvent> {}; // Start Event Next Action Guard msmf::Row < SubState1, InnerEvent, Exit, msmf::none, msmf::none >
Regards, Takatoshi
Hi Takatoshi, you can also use SFINAE without having Event3 know anything about Event2, just don't use is_same but a tag inside Event2. struct Event2 { typedef int inner_event; }; BOOST_MPL_HAS_XXX_TRAIT_DEF(inner_event) you can now write: typename enable_if<has_inner_event<T> >::type ... This way, Event3 does not know Event2 but a "property" of a set of events. Granted, this is not incredibly beautiful but it does the job. Regards, Christophe
participants (3)
-
Christophe Henry
-
Takatoshi Kondo
-
Takatoshi Kondo