state pattern / template

P

pcrepieux

Hi,

I recently meet a problem while "playing" with the state pattern. I was
wondering if each of the member function dedicated to handle events open(),
close(), ack() could be change to something like process(openEv& ev),
process(closeEv& ev), ... no problem with this point. Going further in this
way, i thought that the process member function would be a great candidate
for a template. Hum ... it is not. The process function have to be virtual
in the base state class. Trying to approach something similar, here is what
i did :

I used a variant type (boost::variant) that holds any of my event: typedef
boost::variant<pdu1,pdu2,pdu3> pdu;
In the base state class I defined a virtual process(pdu p) and then a
process(pdu p) in each concrete state class that uses a visitor (inherited
from boost::static_visitor) to call the process(xxxEv).

I'd like to know if this is a pertinent solution or if this simply highlight
that if i need to do something like that, something is wrong in the design.

Pierre
 
V

Victor Bazarov

pcrepieux said:
I recently meet a problem while "playing" with the state pattern. I
was wondering if each of the member function dedicated to handle
events open(), close(), ack() could be change to something like
process(openEv& ev), process(closeEv& ev), ... no problem with this
point. Going further in this way, i thought that the process member
function would be a great candidate for a template. Hum ... it is
not. The process function have to be virtual in the base state class.
Trying to approach something similar, here is what i did :

I used a variant type (boost::variant) that holds any of my event:
typedef boost::variant<pdu1,pdu2,pdu3> pdu;
In the base state class I defined a virtual process(pdu p) and then a
process(pdu p) in each concrete state class that uses a visitor
(inherited from boost::static_visitor) to call the process(xxxEv).

I'd like to know if this is a pertinent solution or if this simply
highlight that if i need to do something like that, something is
wrong in the design.

I would probably make all events inherit from one base Event class
and then make 'process' accept a reference to that, instead of the
'boost::variant'. Every derived class then could check if he has
received the "correct" event by using 'dynamic_cast' or some other
RTTI (or pseudo-RTTI) way. It just seems to me that RT polymorphism
is much more flexible than CT one.

V
 
J

Jeff F

pcrepieux said:
Hi,

I recently meet a problem while "playing" with the state pattern. I was
wondering if each of the member function dedicated to handle events
open(),
close(), ack() could be change to something like process(openEv& ev),
process(closeEv& ev), ... no problem with this point. Going further in
this
way, i thought that the process member function would be a great candidate
for a template. Hum ... it is not. The process function have to be virtual
in the base state class. Trying to approach something similar, here is
what
i did :

I used a variant type (boost::variant) that holds any of my event: typedef
boost::variant<pdu1,pdu2,pdu3> pdu;
In the base state class I defined a virtual process(pdu p) and then a
process(pdu p) in each concrete state class that uses a visitor (inherited
from boost::static_visitor) to call the process(xxxEv).

I'd like to know if this is a pertinent solution or if this simply
highlight
that if i need to do something like that, something is wrong in the
design.

You're already using boost, so have you taken a look at the boost StateChart
library? It is part of the boost_1_34 release. There is also a smaller but
nice state table implementation presented in the Template Metaprogramming
book by Gurtovoy & Abrahams that uses boost mpl.

Jeff Flinn
 
P

pcrepieux

Victor Bazarov said:
I would probably make all events inherit from one base Event class
and then make 'process' accept a reference to that, instead of the
'boost::variant'. Every derived class then could check if he has
received the "correct" event by using 'dynamic_cast' or some other
RTTI (or pseudo-RTTI) way. It just seems to me that RT polymorphism
is much more flexible than CT one.

V

In fact as i can know the type at compile time, i just wanted to avoid
checking it at runtime. I think this would involve something like a "switch
case" in the process function and as a single state can handle many
different event type i just thought this could be bypassed.
What do you mean by "pseudo RTTI" ? Something i could implement myself to
know what derived class is referenced by the base class pointer ?
I often read that using RTTI could be costly ... Not that i try to optimize
code first, but in my case i believe i don't need RTTI (maybe i'm wrong). A
code like this would have make me really happy :

class State{
public:
....
template <class Ev> virtual int process(Ev& ev);
}

State1: public State{
public:
....
int process(Ev1& ev);
int process(Ev2& ev);
}


If RTTI didn't exist, do you see any drawback in doing the job with variant
and visitor ?
 
B

Barry

pcrepieux said:
In fact as i can know the type at compile time, i just wanted to avoid
checking it at runtime. I think this would involve something like a "switch
case" in the process function and as a single state can handle many
different event type i just thought this could be bypassed.
What do you mean by "pseudo RTTI" ? Something i could implement myself to
know what derived class is referenced by the base class pointer ?
I often read that using RTTI could be costly ... Not that i try to optimize
code first, but in my case i believe i don't need RTTI (maybe i'm wrong). A
code like this would have make me really happy :

class State{
public:
...
template <class Ev> virtual int process(Ev& ev);

I don't think virtual member function can be templated
 
V

Victor Bazarov

pcrepieux said:
In fact as i can know the type at compile time, i just wanted to avoid
checking it at runtime. I think this would involve something like a
"switch case" in the process function and as a single state can
handle many different event type i just thought this could be
bypassed.

I use a value in the 'event' instance. An enumeration that can only
be set in the event constructor, for example.
What do you mean by "pseudo RTTI" ? Something i could implement
myself to know what derived class is referenced by the base class
pointer ?

Yes. Some kind of "type ID" in the derived class. Has to be unique
to be useful. If you don't want to use polymorphism (and I am not
blaiming you, to each his own), some other mechanism to emulate it
would be required.
I often read that using RTTI could be costly ... Not that i try to
optimize code first, but in my case i believe i don't need RTTI
(maybe i'm wrong). A code like this would have make me really happy :

class State{
public:
...
template <class Ev> virtual int process(Ev& ev);
}

State1: public State{
public:
...
int process(Ev1& ev);
int process(Ev2& ev);
}


If RTTI didn't exist, do you see any drawback in doing the job with
variant and visitor ?

I am not familiar with inner works of boost::variant (although I have
heard of it and seen folks suggesting it), and I haven't used it in
any of my code (haven't had a need to, I guess). If it works, use it -
that's my motto.

V
 
P

pcrepieux

Victor Bazarov said:
I use a value in the 'event' instance. An enumeration that can only
be set in the event constructor, for example.


Yes. Some kind of "type ID" in the derived class. Has to be unique
to be useful. If you don't want to use polymorphism (and I am not
blaiming you, to each his own), some other mechanism to emulate it
would be required.


I am not familiar with inner works of boost::variant (although I have
heard of it and seen folks suggesting it), and I haven't used it in
any of my code (haven't had a need to, I guess). If it works, use it -
that's my motto.

V

I humbly admit i don't know much about inner work of variant neither, ...
this make me think that i should check a few point with boost users to be
really sure it fulfill my needs.

Thank you for your answers.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top