Search code examples
c++templatesbooststatechart

Boost statechart : trying to implement the inner initial substate of an orthogonal state but compilation fails


seems I cannot implement a substate of an orthogonal state.

When I declare SlewingStartST as the initial inner state of SlewingST, compilation fails :

template <  Tel aTel >
class SlewingST : 
public sc::simple_state < SlewingST<aTel>, SearchingST::orthogonal<int(aTel) - 1 >,SlewingStartST<aTel> >

Below the compilation message :

In file included from src/fsm2.cpp:7:0:
/usr/include/boost/statechart/simple_state.hpp: In instantiation of ‘class boost::statechart::simple_state<SlewingStartST<(Tel)1>, SlewingST<(Tel)1>, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>’:
src/fsm2.cpp:181:7:   required from ‘class SlewingStartST<(Tel)1>’
/usr/include/boost/mpl/aux_/has_tag.hpp:20:1:   required by substitution of ‘template<class U> static char (& boost::mpl::aux::has_tag<SlewingStartST<(Tel)1>, mpl_::bool_<false> >::gcc_3_2_wknd::test<U>(const volatile boost::mpl::aux::type_wrapper<T>*, boost::mpl::aux::type_wrapper<typename U::tag>*))[2] [with U = SlewingStartST<(Tel)1>]’
/usr/include/boost/mpl/aux_/has_tag.hpp:20:1:   required from ‘const bool boost::mpl::aux::has_tag<SlewingStartST<(Tel)1>, mpl_::bool_<false> >::value’
/usr/include/boost/mpl/aux_/has_tag.hpp:20:1:   required from ‘struct boost::mpl::aux::has_tag<SlewingStartST<(Tel)1>, mpl_::bool_<false> >’
/usr/include/boost/mpl/sequence_tag.hpp:110:8:   required from ‘struct boost::mpl::sequence_tag<SlewingStartST<(Tel)1> >’
/usr/include/boost/mpl/begin_end.hpp:33:51:   [ skipping 5 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/statechart/simple_state.hpp:85:7:   required from ‘struct boost::statechart::detail::simple_state_base_type<SlewingST<(Tel)1>, SearchingST, SlewingStartST<(Tel)1> >’
/usr/include/boost/statechart/simple_state.hpp:191:7:   required from ‘class boost::statechart::simple_state<SlewingST<(Tel)1>, boost::statechart::simple_state<SearchingST, CFringeSearchSM, boost::mpl::list<SlewingST<(Tel)1> > >::orthogonal<0>, SlewingStartST<(Tel)1>, (boost::statechart::history_mode)0>’
src/fsm2.cpp:140:7:   required from ‘class SlewingST<(Tel)1>’
/usr/include/boost/statechart/simple_state.hpp:707:42:   required from ‘boost::statechart::result boost::statechart::simple_state<MostDerived, Context, InnerInitial, historyMode>::transit_impl(const TransitionAction&) [with DestinationState = SlewingST<(Tel)1>; TransitionContext = CFringeSearchSM; TransitionAction = boost::statechart::detail::no_transition_function; MostDerived = IdleST; Context = CFringeSearchSM; InnerInitial = boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>; boost::statechart::history_mode historyMode = (boost::statechart::history_mode)0; boost::statechart::result = boost::statechart::detail::safe_reaction_result]’
/usr/include/boost/statechart/simple_state.hpp:313:70:   required from ‘boost::statechart::result boost::statechart::simple_state<MostDerived, Context, InnerInitial, historyMode>::transit() [with DestinationState = SlewingST<(Tel)1>; MostDerived = IdleST; Context = CFringeSearchSM; InnerInitial = boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>; boost::statechart::history_mode historyMode = (boost::statechart::history_mode)0; boost::statechart::result = boost::statechart::detail::safe_reaction_result]’
src/fsm2.cpp:90:45:   required from here
/usr/include/boost/statechart/simple_state.hpp:191:7: error: invalid use of incomplete type ‘class SlewingST<(Tel)1>’
 class simple_state : public detail::simple_state_base_type< MostDerived,

Below the code example :

#include <iostream>
#include <ctime>

#include <boost/array.hpp>
#include <boost/statechart/event.hpp>
#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/state.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/statechart/custom_reaction.hpp>
#include <boost/statechart/in_state_reaction.hpp>
#include <boost/statechart/deep_history.hpp>

using namespace std;
namespace sc = boost::statechart;
namespace mpl = boost::mpl;


// Which telescope are addressing
enum class Tel { TEL1 = 1, TEL2, TEL3, TEL4, TEL5, TEL6 };

// Searching event
struct EvSearching : sc::event< EvSearching > {};

// Parameterized event for telescope loss
template< Tel aTel >
struct EvTelLost : sc::event< EvTelLost< aTel > > {};


class IdleST;
class SearchingST;
template< Tel  aTel> class SlewingST;
class CFringeSearchSM : public sc::state_machine< CFringeSearchSM, IdleST >
{
public:
  // Exposed facilities ------------------------------------------------------------
  // ( Cons / Des) trutor
  CFringeSearchSM() {;}
  ~CFringeSearchSM() {;}
};

class IdleST : public sc::simple_state < IdleST, CFringeSearchSM>
{
public:
  // Exposed facilities ------------------------------------------------------------
  // ( Cons / Des) trutor
  IdleST() {cout << "IdleST created" << endl ;}
  ~IdleST() {cout << "IdleST destroyed" << endl ;}

  // -------------------------------------------------------------------------------
  typedef mpl::list< sc::custom_reaction< EvTelLost<Tel::TEL1> >  > reactions;
  // Reaction to EvSearching
  sc::result react( const EvTelLost<Tel::TEL1>&   )
  {
      const char* cName = typeid(*this).name();
      cout << "curState = " << cName << ", Treating EvTelLost<Tel::TEL1>" << endl;
      return  transit<SlewingST<Tel::TEL1>>();
  } 
};

class SearchingST : public sc::simple_state < SearchingST, CFringeSearchSM, 
                            mpl::list< SlewingST<Tel::TEL1> > >
{
public:
  // Exposed facilities ------------------------------------------------------------
  // ( Cons / Des) trutor
  SearchingST() {cout << "SearchingST created" << endl ;}
  ~SearchingST () {cout << "SearchingST destroyed" << endl ;}
};

template <  Tel aTel > class SlewingStartST ;

template <  Tel aTel >
class SlewingST : 
public sc::simple_state < SlewingST<aTel>, SearchingST::orthogonal<int(aTel) - 1 >,SlewingStartST<aTel> >
{
public:
  // Exposed facilities ------------------------------------------------------------
  // ( Cons / Des) trutor
  SlewingST(){ cout << "SlewingST created" << endl ;}
  ~SlewingST(){ cout << "SlewingST destroyed" << endl ;}

 typedef mpl::list< sc::custom_reaction< EvTelLost<aTel>  > > reactions;

  // Generic interface  ------------------------------------------------------------
  //sc::result react( const EvTelLost< aTel >   )
  sc::result react( const EvTelLost<aTel>   )
  {
    return  this->discard_event();
  }
};

template <  Tel aTel >
class SlewingStartST : 
public sc::simple_state < SlewingStartST<aTel>, SlewingST<aTel> >
{
public:
  // Exposed facilities ------------------------------------------------------------
  // ( Cons / Des) trutor
  SlewingStartST(){ cout << "SlewingStartST created" << endl ;}
  ~SlewingStartST(){ cout << "SlewingStartST destroyed" << endl ;}
};
 
int main()
{
  CFringeSearchSM myFringeSearchSM;
  myFringeSearchSM.initiate();
  myFringeSearchSM.process_event(EvTelLost<Tel::TEL1>());

  return 0;
}

Thanks a lot for your hints !

Sylvain


Solution

  • I had to help a bit the C++ compiler to understand my C++ code ... I had to explicit the template dependent names replacing :

    template <  Tel aTel >
    class SlewingST : 
    public sc::simple_state < SlewingST<aTel>, SearchingST::orthogonal<int(aTel) - 1 >,SlewingStartST<aTel> >
    

    by

    template <  Tel aTel >
    class SlewingST :
    public sc::simple_state < SlewingST<aTel>, typename SearchingST<aTel>::template orthogonal<int(aTel) - 1 >, mpl::list< SlewingStartST<aTel> > >
    

    Notice as well that the last SlewingST class template parameter should be inserted in a mpl::list<>.

    Cheers