Hi Andreas,

> > Besides, all the state machine then should be defined in the header
> > file..
> > Do I miss something? Is there some less weird way to do this?
>
> I'm afraid, I don't see any good way how you could do this. May I ask why
> you'd need to define a reaction for a templated event?
>

 
The application I'm working on is a client that communicates with some proprietry streaming server. The streams are very different in many aspects, so the class representing a stream is designed as a template parametrized by stream type. The above state machine is instantiated from within this parametrized stream class. Basically, the machine is responsible for managing stream states as a result of input events, and propagating "command" objects carried by some events.
In general, such an event is defined as follows:
 
template <class MostDerived, class Command> struct EvCommand : sc::event<MostDerived>
{
protected:
  boost::shared_ptr<Command> command_;
  EvCommand(const boost::shared_ptr<Command> &command) : command_(command)
  {}
public:
  boost::shared_ptr<Command> getCommand() const
  {
    return command_;
  }
};
(intrusive_ptr should be used here, but this doensn't matter right now)
Then, actual "command carriers" are defined this way:
 
struct EvLogin : EvCommand<EvLogin, ProtocolCommands::Login>
{
  EvLogin(const boost::shared_ptr<ProtocolCommands::Login> &command) :
    EvCommand<EvLogin, ProtocolCommands::Login>(command)
  {}
};

...where ProtocolCommands::Login is actual command to be wrapped.
Later, the stream object creates this event and queues it to the state machine scheduler.
The transition action for such an event tipically looks like this:
 
template<class Event> void SomeOuterState::dispatchCommand(const Event &ev)
{
  getCommandDispatcher()->send(ev.getCommand());
}

 
The problem is that sometimes specific command type depends on the stream type and must be "deduced" as a part of stream template instantiation, so it's defined like this:
 
template<class StreamType> struct EvStart : EvCommand<EvStart<StreamType>,
  typename StreamType::StartingCommand>
{
  EvStart(const boost::shared_ptr<typename StreamType::StartingCommand> &command) :
    EvCommand<EvStart, typename StreamType::StartingCommand>(command)
  {}
};

While from the state-chart point of view, the EvStart is always the same, despite the actual command type it carries.
 
Of course, the events could "wrap" just some common interface of the commands, but for some reasons I'd like to preserve the actual type of the command at this stage...
 
So I parametrised all the states, moved the implementation to the header file, and... it ceased to compile! Now it says: "1>d:\dev\servision\projects\windows\thirdparty\boost\boost\statechart\simple_state.hpp(188) : error C2039: 'inner_context_type' : is not a member of 'StreamSession::Active<StreamType>'"
 
Where StreamSession is my asynchronous_state_machine, and the Active is the outermost state. The error occures when trying to instantiate the initial inner state of Active.
 
So I'll appreciate any idea about the cause of the above error, as well as about the approach in general - is it ok or I missuse the framework.
 
Thank you a lot,
 
Igor'.
 


Explore the seven wonders of the world Learn more!