2017-04-13 19 views
0

特定の状況下で遷移を条件付きで防止したいという一般的なガード条件があります。以下は私がやりたがっているC++ /擬似コードです。BOOST :: MSMガード条件での状態遷移の確認

bool operator()(Event const& evt, FSM & fsm, SourceState& src, TargetState& tgt) 
{ 
    bool transition = (current_state != next_state); 
    bool transitionAllowed = (x | y | z); //some custom condition 
    return (transition && transitionAllowed); 
} 

私は、ターゲット状態は、我々は他のパラメータに基づいて遷移を許可することができるかどうかを決定元の状態と異なることに基づいているかどうかを知りたいです。これまでの文書化では大した成果はありませんでした。

答えて

1

質問に2つの部分が含まれているようです。 現在の状態と次の状態を確認する方法の1つです。もう一つは、カスタム条件をチェックする方法です。

現在の状態と次の状態を確認するには、std::is_sameメタ機能を使用できます。ここ

ガードの例である:ここ

struct Guard1 { 
    template <class Event, class Fsm, class Source, class Target> 
    bool operator()(Event const&, Fsm& fsm, Source& src, Target&) const { 
     bool transition = !std::is_same<Source, Target>::value; 
     bool transitionAllowed = x() || fsm.y || src.z; 
     return transition && transitionAllowed; 
    } 
}; 

は遷移表である:

// Transition table 
struct transition_table:mpl::vector< 
    //   Start Event Next Action  Guard 
    //   source and target is the same 
    msmf::Row < State1, Event1, State1, msmf::none, Guard1 >, 

    //   source and target is different 
    msmf::Row < State1, Event2, State2, msmf::none, Guard1 > 
> {}; 

イベント1によって引き起こされる遷移は、同じソースおよびターゲットの状態を有します。どちらもState1です。 Event2によって引き起こされる遷移には、異なるソース状態とターゲット状態があります。ソース状態はState1であり、ターゲット状態はState2で​​す。

前者の場合はstd::is_same<Source, Target>::valueがtrueを返し、後者の場合がfalseを返します。 変数transitionが結果の要約です。

これは戻り値の一部として使用できます。

カスタム条件を評価するには、いくつかのソースから評価用の値を取得する必要があります。 私は3つのソースの例を書いた。

  • x()はグローバル関数です。もちろん、このようなグローバル変数を使用することができます。
  • yは、ステートマシンのメンバ変数です。
  • zは、ソース状態State1のメンバ変数です。ここで

完全なコードです:

#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 <boost/static_assert.hpp> 

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

// You can test changing the value 
bool const example_value = true; 

struct Event1 {}; 
struct Event2 {}; 

// example of a condition 
bool x() { return example_value; } 

struct Sm_:msmf::state_machine_def<Sm_> 
{ 
    // States 
    struct State1:msmf::state<> { 
     template <class Event,class Fsm> 
     void on_entry(Event const&, Fsm&) const { 
      std::cout << "State1::on_entry()" << std::endl; 
     } 
     template <class Event,class Fsm> 
     void on_exit(Event const&, Fsm&) const { 
      std::cout << "State1::on_exit()" << std::endl; 
     } 
     bool z = example_value; // example of a condition 
    }; 
    struct State2:msmf::state<> { 
     template <class Event,class Fsm> 
     void on_entry(Event const&, Fsm&) { 
      std::cout << "State2::on_entry()" << std::endl; 
     } 
     template <class Event,class Fsm> 
     void on_exit(Event const&, Fsm&) const { 
      std::cout << "State2::on_exit()" << std::endl; 
     } 
     int property; 
    }; 
    // Set initial state 
    typedef State1 initial_state; 

    // Guards 
    struct Guard1 { 
     template <class Event, class Fsm, class Source, class Target> 
     bool operator()(Event const&, Fsm& fsm, Source& src, Target&) const { 
      bool transition = !std::is_same<Source, Target>::value; 
      bool transitionAllowed = x() || fsm.y || src.z; 
      return transition && transitionAllowed; 
     } 
    }; 

    // Transition table 
    struct transition_table:mpl::vector< 
     //   Start Event Next Action  Guard 
     //   source and target is the same 
     msmf::Row < State1, Event1, State1, msmf::none, Guard1 >, 

     //   source and target is different 
     msmf::Row < State1, Event2, State2, msmf::none, Guard1 > 
    > {}; 
    bool y = example_value; // example of a condition 
}; 

// Pick a back-end 
typedef msm::back::state_machine<Sm_> Sm; 

int main() { 
    Sm sm; 
    sm.start(); 

    std::cout << "> Send Event1()" << std::endl; 
    sm.process_event(Event1()); 

    std::cout << "> Send Event2()" << std::endl; 
    sm.process_event(Event2()); 
} 

カスタム条件の値を変更することができます。

// You can test changing the value 
bool const example_value = true; 

example_valueをfalseに設定すると、カスタム条件が満たされません。

カスタム条件が満たされない場合、Event1Event2の両方が遷移しません。 カスタム条件が満たされている場合、ソースとターゲットの状態が同じであるため、Event1は遷移しません。 Event2が移行します。

実行中のデモはこちらです。

場合example_value = true

https://wandbox.org/permlink/6qHcW9e6JX4QXAuH

場合example_value = false

https://wandbox.org/permlink/HxaGpAr90YLEc5l8

+0

これはニート溶液です。私はonEntryイベントで取得できる 'stateNum'でソースとターゲットの状態を設定して、これを行う方法を見つけました。 (つまり、実際の状態のonEntryでは、stateNum = fsm.current_state()、現在の状態がそれぞれの状態の一意の状態識別子を指しています) 私はあなたのソリューションが好きです!それは私のものより少しエレガントなようです:-) – Edwin

関連する問題