Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r66592 - in trunk/boost/msm: back front/euml
From: christophe.j.henry_at_[hidden]
Date: 2010-11-15 16:04:54


Author: chenry
Date: 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
New Revision: 66592
URL: http://svn.boost.org/trac/boost/changeset/66592

Log:
- added mpl_graph-based features (for entry states and checking of region orthogonality)
- added Boost.Parameter interface for back-end definition
Added:
   trunk/boost/msm/back/mpl_graph_fsm_check.hpp (contents, props changed)
   trunk/boost/msm/back/no_fsm_check.hpp (contents, props changed)
Text files modified:
   trunk/boost/msm/back/default_compile_policy.hpp | 1
   trunk/boost/msm/back/favor_compile_time.hpp | 1
   trunk/boost/msm/back/history_policies.hpp | 3
   trunk/boost/msm/back/metafunctions.hpp | 143 +++++++++++++++++++++++++++++++++++++++
   trunk/boost/msm/back/state_machine.hpp | 113 ++++++++++++++++++++++++++----
   trunk/boost/msm/front/euml/state_grammar.hpp | 1
   6 files changed, 244 insertions(+), 18 deletions(-)

Modified: trunk/boost/msm/back/default_compile_policy.hpp
==============================================================================
--- trunk/boost/msm/back/default_compile_policy.hpp (original)
+++ trunk/boost/msm/back/default_compile_policy.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -17,6 +17,7 @@
 {
 struct favor_runtime_speed
 {
+ typedef int compile_policy;
     typedef ::boost::mpl::true_ add_forwarding_rows;
 };
 

Modified: trunk/boost/msm/back/favor_compile_time.hpp
==============================================================================
--- trunk/boost/msm/back/favor_compile_time.hpp (original)
+++ trunk/boost/msm/back/favor_compile_time.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -63,6 +63,7 @@
 
 struct favor_compile_time
 {
+ typedef int compile_policy;
     typedef ::boost::mpl::false_ add_forwarding_rows;
 };
 

Modified: trunk/boost/msm/back/history_policies.hpp
==============================================================================
--- trunk/boost/msm/back/history_policies.hpp (original)
+++ trunk/boost/msm/back/history_policies.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -152,6 +152,7 @@
 
 struct NoHistory
 {
+ typedef int history_policy;
     template <int NumberOfRegions>
     struct apply
     {
@@ -160,6 +161,7 @@
 };
 struct AlwaysHistory
 {
+ typedef int history_policy;
     template <int NumberOfRegions>
     struct apply
     {
@@ -169,6 +171,7 @@
 template <class Events>
 struct ShallowHistory
 {
+ typedef int history_policy;
     template <int NumberOfRegions>
     struct apply
     {

Modified: trunk/boost/msm/back/metafunctions.hpp
==============================================================================
--- trunk/boost/msm/back/metafunctions.hpp (original)
+++ trunk/boost/msm/back/metafunctions.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -38,10 +38,15 @@
 #include <boost/mpl/insert_range.hpp>
 #include <boost/mpl/front.hpp>
 #include <boost/mpl/logical.hpp>
+#include <boost/mpl/plus.hpp>
 
 #include <boost/type_traits/is_same.hpp>
 #include <boost/utility/enable_if.hpp>
 
+// mpl_graph graph implementation and depth first search
+#include <boost/msm/mpl_graph/incidence_list_graph.hpp>
+#include <boost/msm/mpl_graph/depth_first_search.hpp>
+
 BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_creation)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit)
@@ -168,6 +173,7 @@
 };
 
 // builds a mpl::vector of initial states
+//TODO remove duplicate from get_initial_states
 template <class region>
 struct get_regions_as_sequence
 {
@@ -374,7 +380,7 @@
         ::boost::mpl::if_<
                  ::boost::mpl::has_key<states, ::boost::mpl::placeholders::_2>,
                  ::boost::mpl::placeholders::_1,
- ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::end<mpl::placeholders::_1>,
+ ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::end< ::boost::mpl::placeholders::_1>,
                              not_a_row< get_wrapped_state< ::boost::mpl::placeholders::_2> > >
>
>::type with_init;
@@ -629,6 +635,141 @@
 {
     typedef typename StateType::initial_event type;
 };
+
+template <class TransitionTable, class InitState>
+struct build_one_orthogonal_region
+{
+ template<typename Row>
+ struct row_to_incidence :
+ ::boost::mpl::vector<
+ ::boost::mpl::pair<
+ typename Row::next_state_type,
+ typename Row::transition_event>,
+ typename Row::current_state_type,
+ typename Row::next_state_type
+ > {};
+ template<typename Row>
+ struct row_to_incidence2 :
+ ::boost::mpl::vector<
+ ::boost::mpl::pair<
+ typename Row::transition_event,
+ typename Row::next_state_type>,
+ typename Row::next_state_type,
+ typename Row::current_state_type
+ > {};
+
+ template <class Seq, class Elt>
+ struct transition_incidence_list_helper
+ {
+ typedef typename ::boost::mpl::push_back< Seq, row_to_incidence< Elt > >::type one_direction;
+ typedef typename ::boost::mpl::push_back< one_direction, row_to_incidence2< Elt > >::type type;
+ };
+
+ typedef typename ::boost::mpl::fold<
+ TransitionTable,
+ ::boost::mpl::vector<>,
+ transition_incidence_list_helper< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
+ >::type transition_incidence_list;
+
+ typedef ::boost::metagraph::mpl_graph::incidence_list_graph<transition_incidence_list>
+ transition_graph;
+
+ struct preordering_dfs_visitor :
+ ::boost::metagraph::mpl_graph::dfs_default_visitor_operations
+ {
+ template<typename Node, typename Graph, typename State>
+ struct discover_vertex :
+ ::boost::mpl::insert<State, Node>
+ {};
+ };
+
+ typedef typename mpl::first<
+ typename ::boost::metagraph::mpl_graph::depth_first_search<
+ transition_graph,
+ preordering_dfs_visitor,
+ ::boost::mpl::set<>,
+ InitState
+ >::type
+ >::type type;
+};
+
+// build a vector of regions states (as a set)
+// one set of states for every region
+// version if initial_state is a not sequence
+template <class TransitionTable, class InitStates,class Enable=void>
+struct build_orthogonal_regions
+{
+ typedef ::boost::mpl::set<typename build_one_orthogonal_region<TransitionTable,InitStates>::type> type;
+};
+
+// version if initial_state is a sequence
+template <class TransitionTable, class InitStates>
+struct build_orthogonal_regions
+ <TransitionTable,InitStates,
+ typename ::boost::enable_if<
+ ::boost::mpl::is_sequence<typename InitStates> >::type >
+{
+ typedef typename
+ ::boost::mpl::fold<
+ InitStates, ::boost::mpl::vector<>,
+ ::boost::mpl::push_back<
+ ::boost::mpl::placeholders::_1,
+ build_one_orthogonal_region< TransitionTable, ::boost::mpl::placeholders::_2 > >
+ >::type type;
+};
+
+template <class GraphAsSeqOfSets, class StateType>
+struct find_region_index
+{
+ typedef typename
+ ::boost::mpl::fold<
+ GraphAsSeqOfSets, ::boost::mpl::pair< ::boost::mpl::int_< -1 > /*res*/, ::boost::mpl::int_<0> /*counter*/ >,
+ ::boost::mpl::if_<
+ ::boost::mpl::has_key< ::boost::mpl::placeholders::_2, StateType >,
+ ::boost::mpl::pair<
+ ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
+ ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
+ >,
+ ::boost::mpl::pair<
+ ::boost::mpl::first< ::boost::mpl::placeholders::_1 >,
+ ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
+ >
+ >
+ >::type result_pair;
+ typedef typename ::boost::mpl::first<result_pair>::type type;
+ enum {value = type::value};
+};
+
+template <typename Sequence, typename Range>
+struct set_insert_range
+{
+ typedef typename ::boost::mpl::fold<
+ Range,Sequence,
+ ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >
+ >::type type;
+};
+
+template <class Fsm>
+struct check_regions_orthogonality
+{
+ typedef typename build_orthogonal_regions<typename Fsm::stt,typename Fsm::initial_states>::type regions;
+
+ typedef typename ::boost::mpl::fold<
+ regions, ::boost::mpl::int_<0>,
+ ::boost::mpl::plus< ::boost::mpl::placeholders::_1 , ::boost::mpl::size< ::boost::mpl::placeholders::_2> >
+ >::type number_of_states_in_regions;
+
+ typedef typename ::boost::mpl::fold<
+ regions,mpl::set0<>,
+ set_insert_range<
+ ::boost::mpl::placeholders::_1,
+ ::boost::mpl::placeholders::_2 >
+ >::type one_big_states_set;
+
+ enum {states_in_regions_raw = number_of_states_in_regions::value};
+ enum {cumulated_states_in_regions_raw = ::boost::mpl::size<one_big_states_set>::value};
+};
+
 // helper to find out if a SM has an active exit state and is therefore waiting for exiting
 template <class StateType,class OwnerFct,class FSM>
 inline

Added: trunk/boost/msm/back/mpl_graph_fsm_check.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/msm/back/mpl_graph_fsm_check.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -0,0 +1,38 @@
+// Copyright 2008 Christophe Henry
+// henry UNDERSCORE christophe AT hotmail DOT com
+// This is an extended version of the state machine available in the boost::mpl library
+// Distributed under the same license as the original.
+// Copyright for the original version:
+// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
+// under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MSM_BACK_MPL_GRAPH_FSM_CHECK_H
+#define BOOST_MSM_BACK_MPL_GRAPH_FSM_CHECK_H
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/msm/back/metafunctions.hpp>
+
+namespace boost { namespace msm { namespace back
+{
+ struct mpl_graph_fsm_check
+ {
+ typedef int fsm_check;
+ // checks that regions are truly orthogonal (one state belongs to 1 region)
+ // using the mpl_graph library (part of metagraph)
+ template <class Fsm>
+ static void check_orthogonality()
+ {
+ BOOST_MPL_ASSERT_RELATION( ::boost::msm::back::check_regions_orthogonality<Fsm>::states_in_regions_raw,
+ ==,
+ ::boost::msm::back::check_regions_orthogonality<Fsm>::cumulated_states_in_regions_raw );
+
+ }
+ };
+
+} } }//boost::msm::back
+
+
+#endif //BOOST_MSM_BACK_MPL_GRAPH_FSM_CHECK_H

Added: trunk/boost/msm/back/no_fsm_check.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/msm/back/no_fsm_check.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -0,0 +1,33 @@
+// Copyright 2008 Christophe Henry
+// henry UNDERSCORE christophe AT hotmail DOT com
+// This is an extended version of the state machine available in the boost::mpl library
+// Distributed under the same license as the original.
+// Copyright for the original version:
+// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
+// under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MSM_BACK_NO_FSM_CHECK_H
+#define BOOST_MSM_BACK_NO_FSM_CHECK_H
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/msm/back/metafunctions.hpp>
+
+namespace boost { namespace msm { namespace back
+{
+ struct no_fsm_check
+ {
+ typedef int fsm_check;
+ // no fsm structure checking
+ template <class Fsm>
+ static void check_orthogonality()
+ {
+ }
+ };
+
+} } }//boost::msm::back
+
+
+#endif //BOOST_MSM_BACK_NO_FSM_CHECK_H

Modified: trunk/boost/msm/back/state_machine.hpp
==============================================================================
--- trunk/boost/msm/back/state_machine.hpp (original)
+++ trunk/boost/msm/back/state_machine.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -22,6 +22,7 @@
 
 #include <boost/mpl/contains.hpp>
 #include <boost/mpl/deref.hpp>
+#include <boost/mpl/assert.hpp>
 
 #include <boost/fusion/container/vector/convert.hpp>
 #include <boost/fusion/include/as_vector.hpp>
@@ -50,6 +51,8 @@
 
 #include <boost/serialization/base_object.hpp>
 
+#include <boost/parameter.hpp>
+
 #include <boost/msm/row_tags.hpp>
 #include <boost/msm/back/fold_to_list.hpp>
 #include <boost/msm/back/metafunctions.hpp>
@@ -59,6 +62,7 @@
 #include <boost/msm/back/args.hpp>
 #include <boost/msm/back/default_compile_policy.hpp>
 #include <boost/msm/back/dispatch_table.hpp>
+#include <boost/msm/back/no_fsm_check.hpp>
 
 BOOST_MPL_HAS_XXX_TRAIT_DEF(accept_sig)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(no_automatic_create)
@@ -66,6 +70,9 @@
 BOOST_MPL_HAS_XXX_TRAIT_DEF(direct_entry)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(initial_event)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(do_serialize)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(history_policy)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(fsm_check)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(compile_policy)
 
 #ifndef BOOST_MSM_CONSTRUCTOR_ARG_SIZE
 #define BOOST_MSM_CONSTRUCTOR_ARG_SIZE 5 // default max number of arguments for constructors
@@ -89,15 +96,64 @@
 const boost::msm::back::dispatch_table<Fsm,Stt, Event,CompilePolicy>
 dispatch_table<Fsm,Stt, Event,CompilePolicy>::instance;
 
+BOOST_PARAMETER_TEMPLATE_KEYWORD(front_end)
+BOOST_PARAMETER_TEMPLATE_KEYWORD(history_policy)
+BOOST_PARAMETER_TEMPLATE_KEYWORD(compile_policy)
+BOOST_PARAMETER_TEMPLATE_KEYWORD(fsm_check_policy)
+
+typedef ::boost::parameter::parameters<
+ ::boost::parameter::required< ::boost::msm::back::tag::front_end >
+ , ::boost::parameter::optional<
+ ::boost::parameter::deduced< ::boost::msm::back::tag::history_policy>, has_history_policy< ::boost::mpl::_ >
+ >
+ , ::boost::parameter::optional<
+ ::boost::parameter::deduced< ::boost::msm::back::tag::compile_policy>, has_compile_policy< ::boost::mpl::_ >
+ >
+ , ::boost::parameter::optional<
+ ::boost::parameter::deduced< ::boost::msm::back::tag::fsm_check_policy>, has_fsm_check< ::boost::mpl::_ >
+ >
+> state_machine_signature;
+
+
 
 // library-containing class for state machines. Pass the actual FSM class as
 // the Concrete parameter.
-template<class Derived,class HistoryPolicy=NoHistory,class CompilePolicy=favor_runtime_speed>
-class state_machine : public Derived
+// A0=Derived,A1=NoHistory,A2=CompilePolicy,A3=FsmCheckPolicy >
+template <
+ class A0
+ , class A1 = parameter::void_
+ , class A2 = parameter::void_
+ , class A3 = parameter::void_
+>
+class state_machine : //public Derived
+ public ::boost::parameter::binding<
+ typename state_machine_signature::bind<A0,A1,A2,A3>::type, ::boost::msm::back::tag::front_end
+ >::type
 {
+public:
+ // Create ArgumentPack
+ typedef typename
+ state_machine_signature::bind<A0,A1,A2,A3>::type
+ state_machine_args;
+
+ // Extract first logical parameter.
+ typedef typename ::boost::parameter::binding<
+ state_machine_args, ::boost::msm::back::tag::front_end>::type Derived;
+
+ typedef typename ::boost::parameter::binding<
+ state_machine_args, ::boost::msm::back::tag::history_policy, NoHistory >::type HistoryPolicy;
+
+ typedef typename ::boost::parameter::binding<
+ state_machine_args, ::boost::msm::back::tag::compile_policy, favor_runtime_speed >::type CompilePolicy;
+
+ typedef typename ::boost::parameter::binding<
+ state_machine_args, ::boost::msm::back::tag::fsm_check_policy, no_fsm_check >::type FsmCheckPolicy;
+
+
 private:
- typedef boost::msm::back::state_machine<Derived,
- HistoryPolicy,CompilePolicy> library_sm;
+
+ typedef boost::msm::back::state_machine<
+ A0,A1,A2,A3> library_sm;
 
     typedef ::boost::function<
         execute_return ()> transition_fct;
@@ -108,7 +164,7 @@
     typedef bool (*flag_handler)(library_sm&);
 
     // all state machines are friend with each other to allow embedding any of them in another fsm
- template <class ,class , class
+ template <class ,class , class, class
> friend class boost::msm::back::state_machine;
 
     // helper to add, if needed, visitors to all states
@@ -1267,7 +1323,7 @@
      }
 
      // Construct with the default initial states
- state_machine<Derived,HistoryPolicy,CompilePolicy >()
+ state_machine<A0,A1,A2,A3 >()
          :Derived()
          ,m_events_queue()
          ,m_deferred_events_queue()
@@ -1285,7 +1341,7 @@
          fill_states(this);
      }
      template <class Expr>
- state_machine<Derived,HistoryPolicy,CompilePolicy >
+ state_machine<A0,A1,A2,A3 >
          (Expr const& expr,typename ::boost::enable_if<typename ::boost::proto::is_expr<Expr>::type >::type* =0)
          :Derived()
          ,m_events_queue()
@@ -1313,7 +1369,7 @@
 #define MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB(z, n, unused) ARG ## n t ## n
 #define MSM_CONSTRUCTOR_HELPER_EXECUTE(z, n, unused) \
         template <BOOST_PP_ENUM_PARAMS(n, class ARG)> \
- state_machine<Derived,HistoryPolicy,CompilePolicy \
+ state_machine<A0,A1,A2,A3 \
>(BOOST_PP_ENUM(n, MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB, ~ ), \
         typename ::boost::disable_if<typename ::boost::proto::is_expr<ARG0>::type >::type* =0 ) \
         :Derived(BOOST_PP_ENUM_PARAMS(n,t)) \
@@ -1331,7 +1387,7 @@
          fill_states(this); \
      } \
         template <class Expr,BOOST_PP_ENUM_PARAMS(n, class ARG)> \
- state_machine<Derived,HistoryPolicy,CompilePolicy \
+ state_machine<A0,A1,A2,A3 \
>(Expr const& expr,BOOST_PP_ENUM(n, MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB, ~ ), \
         typename ::boost::enable_if<typename ::boost::proto::is_expr<Expr>::type >::type* =0 ) \
         :Derived(BOOST_PP_ENUM_PARAMS(n,t)) \
@@ -1372,7 +1428,7 @@
          }
         return *this;
      }
- state_machine<Derived,HistoryPolicy,CompilePolicy>
+ state_machine<A0,A1,A2,A3>
          (library_sm const& rhs)
          : Derived(rhs)
      {
@@ -2046,6 +2102,26 @@
          region_start_helper< ::boost::mpl::int_<0> >::do_start(this,incomingEvent);
      }
 
+ template <class StateType>
+ struct find_region_id
+ {
+ template <int region>
+ struct In
+ {
+ enum {region_index=region};
+ };
+ // if the user provides no region, find it!
+ template<>
+ struct In<-1>
+ {
+ typedef typename build_orthogonal_regions<
+ stt,
+ typename Derived::initial_state
+ >::type all_regions;
+ enum {region_index= find_region_index<all_regions,StateType>::value };
+ };
+ enum {region_index = In<StateType::zone_index>::region_index };
+ };
      // helper used to set the correct state as active state upon entry into a fsm
      struct direct_event_start_helper
      {
@@ -2074,10 +2150,10 @@
          {
              (static_cast<Derived*>(self))->on_entry(evt,fsm);
              int state_id = get_state_id<stt,typename EventType::active_state::wrapped_entry>::value;
- BOOST_STATIC_ASSERT(EventType::active_state::zone_index >= 0);
- BOOST_STATIC_ASSERT(EventType::active_state::zone_index <= nr_regions::value);
+ BOOST_STATIC_ASSERT(find_region_id<typename EventType::active_state::wrapped_entry>::region_index >= 0);
+ BOOST_STATIC_ASSERT(find_region_id<typename EventType::active_state::wrapped_entry>::region_index <= nr_regions::value);
              // just set the correct zone, the others will be default/history initialized
- self->m_states[EventType::active_state::zone_index] = state_id;
+ self->m_states[find_region_id<typename EventType::active_state::wrapped_entry>::region_index] = state_id;
              self->start(evt.m_event);
          }
 
@@ -2113,7 +2189,7 @@
              (static_cast<Derived*>(self))->on_entry(evt,fsm);
              int state_id = get_state_id<stt,typename EventType::active_state::wrapped_entry>::value;
              // given region starts with the entry pseudo state as active state
- self->m_states[EventType::active_state::zone_index] = state_id;
+ self->m_states[find_region_id<typename EventType::active_state::wrapped_entry>::region_index] = state_id;
              self->start(evt.m_event);
              // and we process the transition in the zone of the newly active state
              // (entry pseudo states are, according to UML, a state connecting 1 transition outside to 1 inside
@@ -2131,9 +2207,9 @@
              void operator()( ::boost::msm::wrap<StateType> const& )
              {
                  int state_id = get_state_id<stt,typename StateType::wrapped_entry>::value;
- BOOST_STATIC_ASSERT(StateType::zone_index >= 0);
- BOOST_STATIC_ASSERT(StateType::zone_index <= nr_regions::value);
- helper_self->m_states[StateType::zone_index] = state_id;
+ BOOST_STATIC_ASSERT(find_region_id<typename StateType::wrapped_entry>::region_index >= 0);
+ BOOST_STATIC_ASSERT(find_region_id<typename StateType::wrapped_entry>::region_index <= nr_regions::value);
+ helper_self->m_states[find_region_id<typename StateType::wrapped_entry>::region_index] = state_id;
              }
          private:
              library_sm* helper_self;
@@ -2322,6 +2398,9 @@
     template <class ContainingSM>
     void fill_states(ContainingSM* containing_sm=0)
     {
+ // checks that regions are truly orthogonal
+ FsmCheckPolicy::template check_orthogonality<library_sm>();
+
         BOOST_STATIC_CONSTANT(int, max_state = (mpl::size<state_list>::value));
         // allocate the place without reallocation
         m_visitors.fill_visitors(max_state);

Modified: trunk/boost/msm/front/euml/state_grammar.hpp
==============================================================================
--- trunk/boost/msm/front/euml/state_grammar.hpp (original)
+++ trunk/boost/msm/front/euml/state_grammar.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -18,6 +18,7 @@
 
 #include <boost/mpl/remove_if.hpp>
 #include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/assert.hpp>
 
 #include <boost/msm/row_tags.hpp>
 #include <boost/msm/front/common_states.hpp>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk