为什么boost :: msm :: front :: state_machine只能为其转换表支持多达10个状态?

时间:2018-02-27 09:48:06

标签: c++ boost state-machine boost-msm

我正在尝试使用多个状态,警卫和操作来设置我自己的状态机,但是当转换表中的状态数超过10个状态时,会弹出大量错误消息,但我仍然无法从中推断出错误的来源他们。我简化了我的代码:

/* Boost MSM */
#include <boost/msm/back/state_machine.hpp>

#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <boost/msm/back/mpl_graph_fsm_check.hpp>

/* STL */
#include <memory>

namespace msm = boost::msm ;
namespace msmf = boost::msm::front ;
namespace msmb = boost::msm::back ;
namespace mpl = boost::mpl ;

#define None \
    msmf::none

namespace {

class Shelf_Hooking ;
// typedef msmb::state_machine<Shelf_Hooking> SM_ ;
typedef msmb::state_machine<Shelf_Hooking, msmb::mpl_graph_fsm_check> SM_ ;

struct Event {} ;

class Shelf_Hooking : public msmf::state_machine_def<Shelf_Hooking> {
    /* States */
    struct A ;
    struct B ;
    struct C ;
    struct D ;
    struct E ;
    struct F ;
    struct G ;
    struct H ;
    struct I ;
    struct J ;
    struct K ;
    struct L ;
    struct M ;
    struct End ;

public:
    Shelf_Hooking() {} ;
    ~Shelf_Hooking() {} ;
    typedef A initial_state ;

    struct transition_table : mpl::vector<
      msmf::Row < A, Event, B, None, None >
    , msmf::Row < B, None, C, None, None >
    , msmf::Row < C, None, D, None, None >
    , msmf::Row < D, None, E, None, None >
    , msmf::Row < E, None, F, None, None >
    , msmf::Row < F, None, G, None, None >
    , msmf::Row < G, None, H, None, None >
    , msmf::Row < H, None, I, None, None >
    , msmf::Row < I, None, J, None, None >
    , msmf::Row < J, None, K, None, None >
    , msmf::Row < K, None, L, None, None >
    , msmf::Row < L, None, M, None, None >
    , msmf::Row < M, None, End, None, None >
    >{} ;

private:
    struct A : public msmf::state<> {} ;
    struct B : public msmf::state<> {} ;
    struct C : public msmf::state<> {} ;
    struct D : public msmf::state<> {} ;
    struct E : public msmf::state<> {} ;
    struct F : public msmf::state<> {} ;
    struct G : public msmf::state<> {} ;
    struct H : public msmf::state<> {} ;
    struct I : public msmf::state<> {} ;
    struct J : public msmf::state<> {} ;
    struct K : public msmf::state<> {} ;
    struct L : public msmf::state<> {} ;
    struct M : public msmf::state<> {} ;
    struct End : public msmf::terminate_state<> {} ;

} ; /* End of State Machine class */

/***************************************************************/
/* Back-end */
class state_machine_impl{
    std::unique_ptr<SM_> state_machine ;

public:
    state_machine_impl() 
    : state_machine(new SM_()) {}

    ~state_machine_impl() {}

    void runSM() {
    state_machine->start() ;
    state_machine->process_event( Event() ) ;
    } /* End of runSM() */

} ; /* End of class state_machine_impl */

} /* End of namespace */

int main() {
    std::unique_ptr<state_machine_impl> Sm_= 
    std::unique_ptr<state_machine_impl>(new state_machine_impl() ) ;

    Sm_->runSM() ;
    return 0 ;
}

如果我只将所有转换都转换为状态J,则转换表有效,但是一旦我添加从J到K的转换,编译器将抛出一个覆盖20,000。+行的错误。我的问题是:

如何在转换表中插入10个以上的状态,警卫和操作而不会产生任何错误?

提前谢谢!

编译器错误消息:

Scanning dependencies of target test_multiple_states
[ 86%] Building CXX object CMakeFiles/test_multiple_states.dir/src/test_multiple_states.cpp.o
In file included from /usr/include/boost/fusion/include/as_set.hpp:11:0,
         from /usr/include/boost/msm/back/state_machine.hpp:28,
         from /home/charly/My_programming_exercises/finite_state_machine/src/test_multiple_states.cpp:2:
/usr/include/boost/fusion/container/set/convert.hpp: In instantiation of ‘struct boost::fusion::result_of::as_set<boost::mpl::s_item<{anonymous}::Shelf_Hooking::K, boost::mpl::s_item<{anonymous}::Shelf_Hooking::J, boost::mpl::s_item<{anonymous}::Shelf_Hooking::I, boost::mpl::s_item<{anonymous}::Shelf_Hooking::H, boost::mpl::s_item<{anonymous}::Shelf_Hooking::G, boost::mpl::s_item<{anonymous}::Shelf_Hooking::F, boost::mpl::s_item<{anonymous}::Shelf_Hooking::E, boost::mpl::s_item<{anonymous}::Shelf_Hooking::D, boost::mpl::s_item<{anonymous}::Shelf_Hooking::C, boost::mpl::s_item<{anonymous}::Shelf_Hooking::B, boost::mpl::s_item<{anonymous}::Shelf_Hooking::A, boost::mpl::set0<> > > > > > > > > > > > >’:
/usr/include/boost/msm/back/state_machine.hpp:1169:75:   required from ‘class boost::msm::back::state_machine<{anonymous}::Shelf_Hooking, boost::msm::back::mpl_graph_fsm_check>’
/home/charly/My_programming_exercises/finite_state_machine/src/test_multiple_states.cpp:94:29:   required from here
/usr/include/boost/fusion/container/set/convert.hpp:27:13: error: invalid use of incomplete type ‘struct boost::fusion::detail::barrier::as_set<11>’
         type;
         ^
In file included from /usr/include/boost/fusion/container/set/convert.hpp:11:0,
         from /usr/include/boost/fusion/include/as_set.hpp:11,
         from /usr/include/boost/msm/back/state_machine.hpp:28,
         from /home/charly/My_programming_exercises/finite_state_machine/src/test_multiple_states.cpp:2:
/usr/include/boost/fusion/container/set/detail/as_set.hpp:28:12: note: declaration of ‘struct boost::fusion::detail::barrier::as_set<11>’
     struct as_set;
        ^
In file included from /home/charly/My_programming_exercises/finite_state_machine/src/test_multiple_states.cpp:2:0:
/usr/include/boost/msm/back/state_machine.hpp: In instantiation of ‘boost::msm::back::state_machine<A0, A1, A2, A3, A4>::state_machine() [with A0 = {anonymous}::Shelf_Hooking; A1 = boost::msm::back::mpl_graph_fsm_check; A2 = boost::parameter::void_; A3 = boost::parameter::void_; A4 = boost::parameter::void_]’:
/home/charly/My_programming_exercises/finite_state_machine/src/test_multiple_states.cpp:94:29:   required from here
/usr/include/boost/msm/back/state_machine.hpp:1591:27: error: using invalid field ‘boost::msm::back::state_machine<A0, A1, A2, A3, A4>::m_substate_list’
      ,m_substate_list()
               ^
/usr/include/boost/msm/back/state_machine.hpp: In instantiation of ‘void boost::msm::back::state_machine<A0, A1, A2, A3, A4>::call_init<Event>::operator()(const boost::msm::wrap<State>&) [with State = {anonymous}::Shelf_Hooking::A; Event = boost::msm::back::state_machine<{anonymous}::Shelf_Hooking, boost::msm::back::mpl_graph_fsm_check>::InitEvent; A0 = {anonymous}::Shelf_Hooking; A1 = boost::msm::back::mpl_graph_fsm_check; A2 = boost::parameter::void_; A3 = boost::parameter::void_; A4 = boost::parameter::void_]’:
/usr/include/boost/mpl/for_each.hpp:78:26:   required from ‘static void boost::mpl::aux::for_each_impl<false>::execute(Iterator*, LastIterator*, TransformFunc*, F) [with Iterator = boost::mpl::v_iter<boost::mpl::v_item<{anonymous}::Shelf_Hooking::A, boost::mpl::vector0<mpl_::na>, 0>, 0l>; LastIterator = boost::mpl::v_iter<boost::mpl::v_item<{anonymous}::Shelf_Hooking::A, boost::mpl::vector0<mpl_::na>, 0>, 1l>; TransformFunc = boost::msm::wrap<mpl_::arg<1> >; F = boost::msm::back::state_machine<{anonymous}::Shelf_Hooking, boost::msm::back::mpl_graph_fsm_check>::call_init<boost::msm::back::state_machine<{anonymous}::Shelf_Hooking, boost::msm::back::mpl_graph_fsm_check>::InitEvent>]’
/usr/include/boost/mpl/for_each.hpp:105:18:   required from ‘void boost::mpl::for_each(F, Sequence*, TransformOp*) [with Sequence = boost::mpl::v_item<{anonymous}::Shelf_Hooking::A, boost::mpl::vector0<mpl_::na>, 0>; TransformOp = boost::msm::wrap<mpl_::arg<1> >; F = boost::msm::back::state_machine<{anonymous}::Shelf_Hooking, boost::msm::back::mpl_graph_fsm_check>::call_init<boost::msm::back::state_machine<{anonymous}::Shelf_Hooking, boost::msm::back::mpl_graph_fsm_check>::InitEvent>]’
/usr/include/boost/msm/back/state_machine.hpp:1225:13:   required from ‘void boost::msm::back::state_machine<A0, A1, A2, A3, A4>::start() [with A0 = {anonymous}::Shelf_Hooking; A1 = boost::msm::back::mpl_graph_fsm_check; A2 = boost::parameter::void_; A3 = boost::parameter::void_; A4 = boost::parameter::void_]’
/home/charly/My_programming_exercises/finite_state_machine/src/test_multiple_states.cpp:99:30:   required from here
/usr/include/boost/msm/back/state_machine.hpp:2085:57: error: ‘boost::msm::back::state_machine<{anonymous}::Shelf_Hooking, boost::msm::back::mpl_graph_fsm_check>::library_sm {aka class boost::msm::back::state_machine<{anonymous}::Shelf_Hooking, boost::msm::back::mpl_graph_fsm_check>}’ has no member named ‘m_substate_list’
         execute_entry(::boost::fusion::at_key<State>(self->m_substate_list),evt,*self);
                             ^
(...)

/usr/include/boost/msm/back/state_machine.hpp:671:58: error: ‘boost::msm::back::state_machine<{anonymous}::Shelf_Hooking, boost::msm::back::mpl_graph_fsm_check>::library_sm {aka class boost::msm::back::state_machine<{anonymous}::Shelf_Hooking, boost::msm::back::mpl_graph_fsm_check>}’ has no member named ‘m_substate_list’
         (::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),evt,fsm);
                              ^
CMakeFiles/test_multiple_states.dir/build.make:62: recipe for target 'CMakeFiles/test_multiple_states.dir/src/test_multiple_states.cpp.o' failed
make[2]: *** [CMakeFiles/test_multiple_states.dir/src/test_multiple_states.cpp.o] Error 1
CMakeFiles/Makefile2:400: recipe for target 'CMakeFiles/test_multiple_states.dir/all' failed
make[1]: *** [CMakeFiles/test_multiple_states.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

1 个答案:

答案 0 :(得分:0)

使用c ++ 11编译器编译最近的提升:

  

PS 不要滥用#define类型别名

Live On Coliru (Clang)

#include <boost/msm/back/state_machine.hpp>

#include <boost/msm/back/mpl_graph_fsm_check.hpp>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <boost/msm/front/state_machine_def.hpp>

#include <memory>

namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace msmb = boost::msm::back;
namespace mpl = boost::mpl;
using None = msmf::none;

namespace {

    class Shelf_Hooking;
    // typedef msmb::state_machine<Shelf_Hooking> SM_ ;
    typedef msmb::state_machine<Shelf_Hooking, msmb::mpl_graph_fsm_check> SM_;

    struct Event {};

    class Shelf_Hooking : public msmf::state_machine_def<Shelf_Hooking> {
        /* States */
        struct A;
        struct B;
        struct C;
        struct D;
        struct E;
        struct F;
        struct G;
        struct H;
        struct I;
        struct J;
        struct K;
        struct L;
        struct M;
        struct End;

      public:
        Shelf_Hooking(){};
        ~Shelf_Hooking(){};
        typedef A initial_state;

        struct transition_table : mpl::vector<
              msmf::Row<A, Event, B, None, None>, 
              msmf::Row<B, None, C, None, None>,
              msmf::Row<C, None, D, None, None>, 
              msmf::Row<D, None, E, None, None>,
              msmf::Row<E, None, F, None, None>, 
              msmf::Row<F, None, G, None, None>,
              msmf::Row<G, None, H, None, None>, 
              msmf::Row<H, None, I, None, None>,
              msmf::Row<I, None, J, None, None>, 
              msmf::Row<J, None, K, None, None>,
              msmf::Row<K, None, L, None, None>, 
              msmf::Row<L, None, M, None, None>,
              msmf::Row<M, None, End, None, None> > {};

      private:
        struct A : public msmf::state<> {};
        struct B : public msmf::state<> {};
        struct C : public msmf::state<> {};
        struct D : public msmf::state<> {};
        struct E : public msmf::state<> {};
        struct F : public msmf::state<> {};
        struct G : public msmf::state<> {};
        struct H : public msmf::state<> {};
        struct I : public msmf::state<> {};
        struct J : public msmf::state<> {};
        struct K : public msmf::state<> {};
        struct L : public msmf::state<> {};
        struct M : public msmf::state<> {};
        struct End : public msmf::terminate_state<> {};

    }; /* End of State Machine class */

    /***************************************************************/
    /* Back-end */
    class state_machine_impl {
        std::unique_ptr<SM_> state_machine;

      public:
        state_machine_impl() : state_machine(new SM_()) {}

        ~state_machine_impl() {}

        void runSM() {
            state_machine->start();
            state_machine->process_event(Event());
        } /* End of runSM() */

    }; /* End of class state_machine_impl */

} /* End of namespace */

int main() {
    std::unique_ptr<state_machine_impl> Sm_ = std::unique_ptr<state_machine_impl>(new state_machine_impl());

    Sm_->runSM();
}