0

I understood that if the transition for handling the event of Derived was not declared. I will got an error of no transition. It's OK. Here is the example about it.

#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <stdint.h>
#include <assert.h>


struct Base {};
struct Derived : public Base {};

namespace {
    namespace msm = boost::msm;
    namespace msmf = boost::msm::front;
    namespace mpl = boost::mpl;

    // ----- State machine
    struct Sm1_ :msmf::state_machine_def<Sm1_>
    {
        template <class FSM, class Event>
        void no_transition(Event const&, FSM&, int)
        {
            std::cout << "no_transition" << std::endl;
        }

        struct transition1 {
            template <class Event, class Fsm, class SourceState, class TargetState>
            void operator()(Event const& e, Fsm&, SourceState&, TargetState&) const
            {
                std::cout << "transition1()" << std::endl;
            }
        };
        struct transition2 {
            template <class Event, class Fsm, class SourceState, class TargetState>
            void operator()(Event const& e, Fsm&, SourceState&, TargetState&) const
            {
                std::cout << "transition2()" << std::endl;
            }
        };

        // States
        struct State1 :msmf::state<>
        {
            // Entry action
            template <class Event, class Fsm>
            void on_entry(Event const&, Fsm&) const {
                //std::cout << "State1::on_entry()" << std::endl;
            }
            // Exit action
            template <class Event, class Fsm>
            void on_exit(Event const&, Fsm&) const {
                //std::cout << "State1::on_exit()" << std::endl;
            }
        };

        // Set initial state
        typedef State1 initial_state;

        // Internal Transition table
        struct internal_transition_table :mpl::vector<
            //               Event              Action                  Guard
            msmf::Internal < Base,              transition1,            msmf::none >
            //msmf::Internal < Derived,           transition2,            msmf::none >
        > {};
    };

    // Pick a back-end
    typedef msm::back::state_machine<Sm1_> Sm1;

    void test()
    {
        Sm1 sm1;
        sm1.start();

        std::cout << "\n> Send Base" << std::endl;
        sm1.process_event(Base());

        std::cout << "\n> Send Derived" << std::endl;
        sm1.process_event(Derived());
    }
}

int main()
{
    test();
    return 0;
}

output:

> Send Base
transition1()

> Send Derived
no_transition

But if I moved the transition table to the State1, then, the event of Derived was handled by the transition1().

Here is the full example,

#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <stdint.h>
#include <assert.h>


struct Base {};
struct Derived : public Base {};

namespace {
    namespace msm = boost::msm;
    namespace msmf = boost::msm::front;
    namespace mpl = boost::mpl;

    // ----- State machine
    struct Sm1_ :msmf::state_machine_def<Sm1_>
    {
        template <class FSM, class Event>
        void no_transition(Event const&, FSM&, int)
        {
            std::cout << "no_transition" << std::endl;
        }

        struct transition1 {
            template <class Event, class Fsm, class SourceState, class TargetState>
            void operator()(Event const& e, Fsm&, SourceState&, TargetState&) const
            {
                std::cout << "transition1()" << std::endl;
            }
        };
        struct transition2 {
            template <class Event, class Fsm, class SourceState, class TargetState>
            void operator()(Event const& e, Fsm&, SourceState&, TargetState&) const
            {
                std::cout << "transition2()" << std::endl;
            }
        };

        // States
        struct State1 :msmf::state<>
        {
            // Entry action
            template <class Event, class Fsm>
            void on_entry(Event const&, Fsm&) const {
                //std::cout << "State1::on_entry()" << std::endl;
            }
            // Exit action
            template <class Event, class Fsm>
            void on_exit(Event const&, Fsm&) const {
                //std::cout << "State1::on_exit()" << std::endl;
            }

            // Internal Transition table
            struct internal_transition_table :mpl::vector<
                //               Event              Action                  Guard
                msmf::Internal < Base, transition1, msmf::none >
                //msmf::Internal < Derived,           transition2,            msmf::none >
            > {};
        };

        // Set initial state
        typedef State1 initial_state;
    };

    // Pick a back-end
    typedef msm::back::state_machine<Sm1_> Sm1;

    void test()
    {
        Sm1 sm1;
        sm1.start();

        std::cout << "\n> Send Base" << std::endl;
        sm1.process_event(Base());

        std::cout << "\n> Send Derived" << std::endl;
        sm1.process_event(Derived());
    }
}

int main()
{
    test();
    return 0;
}

output:

> Send Base
transition1()

> Send Derived
transition1()

My question are as follows,

  1. Is that attempting to use a parent class name to declare the transition meanwhile expecting the stat machine to handle the event of derived class, which won't work. (yes, I found there is a similar question boost msm cannot processing polymorphic event?)
  2. But why did it work in the second example?
Flames
  • 1
  • 1

0 Answers0