看來你的問題包含兩部分。 一個是如何檢查當前狀態和下一個狀態。另一個是如何檢查自定義條件。
爲了檢查當前狀態和下一個狀態,可以使用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
是結果的嘮叨。
您可以將此用作返回值的一部分。
爲了評估自定義條件,您需要從某些來源獲取評估值。 我寫了三個來源的例子。
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,則不滿足自定義條件。
如果不滿足自定義條件,則Event1
和Event2
都不會進行轉換。 如果自定義條件得到滿足,Event1
不會進行轉換,因爲源和目標狀態相同。 Event2
進行了轉換。
這裏是正在運行的演示。
殼體example_value = true
https://wandbox.org/permlink/6qHcW9e6JX4QXAuH
殼體example_value = false
https://wandbox.org/permlink/HxaGpAr90YLEc5l8
這是純溶液。我找到了一種方法來做到這一點,通過使用onEntry事件中的'stateNum'來填充源和目標狀態。 (即在實際狀態的onEntry中,stateNum = fsm.current_state(),其中當前狀態分別指向每個狀態的唯一狀態標識符) 雖然我喜歡你的解決方案!這看起來比我更優雅一些:-) – Edwin