views:

28

answers:

1

As per the example in the documentation I made the following code that fails to compile because custom_reaction<> does not seem to match the concept expected as the third template parameter to state<>. How do I really make choice points? (I also asked this on the boost list)

#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/state.hpp>
#include <boost/statechart/custom_reaction.hpp>
#include <boost/statechart/event.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/mpl/list.hpp>

#include <iostream>

namespace sc = boost::statechart;

struct make_choice : sc::event< make_choice > {};

// universal choice point base class template
template< class MostDerived, class Context >
struct choice_point : sc::state< MostDerived, Context, 
  sc::custom_reaction< make_choice > >
{
  typedef sc::state< MostDerived, Context, 
    sc::custom_reaction< make_choice > > base_type;
  typedef typename base_type::my_context my_context;
  typedef choice_point my_base;

  choice_point( my_context ctx ) : base_type( ctx )
  {
    this->post_event( boost::intrusive_ptr< make_choice >(
      new make_choice() ) );
  }
};

// ...

struct MyChoicePoint;
struct Machine : sc::state_machine< Machine, MyChoicePoint > {};

struct Dest1 : sc::simple_state< Dest1, Machine > {};
struct Dest2 : sc::simple_state< Dest2, Machine > 
{
  Dest2() { std::cout << "Dest2\n"; }
};
struct Dest3 : sc::simple_state< Dest3, Machine > {};

struct MyChoicePoint : choice_point< MyChoicePoint, Machine >
{
  MyChoicePoint( my_context ctx ) : my_base( ctx ) {}

  sc::result react( const make_choice & )
  {
    if ( 0 )
    {
      return transit< Dest1 >();
    }
    else if ( 1 )
    {
      return transit< Dest2 >();
    }
    else
    {
      return transit< Dest3 >();
    }
  }
};

int main()
{
  Machine machine;
  machine.initiate();

  std::cin.get();
}
A: 

I think I might have found the answer. I'll wait for verification from the boost list but it looks like the document is just wrong and if you follow the directions in the camera example for making custom reactions it works fine. Namely the choice_point template needs to change to this:

// universal choice point base class template
template< class MostDerived, class Context >
struct choice_point : sc::state< MostDerived, Context >
{
  typedef sc::state< MostDerived, Context > base_type;
  typedef typename base_type::my_context my_context;
  typedef choice_point my_base;

  typedef sc::custom_reaction<make_choice> reactions;

  choice_point( my_context ctx ) : base_type( ctx )
  {
    this->post_event( boost::intrusive_ptr< make_choice >(
      new make_choice() ) );
  }
};

This appears to work but I'll wait a bit in case the experts tell me it's wrong.

Noah Roberts
ok, well no reply in boost.user and nobody else has an answer. This appears to work so far so I'm accepting my own answer.
Noah Roberts