C++ Boost MetaStateMachine定義狀態(tài)機超詳細(xì)講解
一、說明
Boost.MetaStateMachine 用于定義狀態(tài)機。狀態(tài)機通過對象的狀態(tài)來描述對象。它們描述了存在哪些狀態(tài)以及狀態(tài)之間可能存在哪些轉(zhuǎn)換。
Boost.MetaStateMachine 提供了三種不同的方式來定義狀態(tài)機。創(chuàng)建狀態(tài)機所需編寫的代碼取決于前端。
如果使用基本前端或函數(shù)前端,則可以用常規(guī)方式定義狀態(tài)機:創(chuàng)建類,從 Boost.MetaStateMachine 提供的其他類派生它們,定義所需的成員變量,并編寫所需的 C++自己編碼?;厩岸撕秃瘮?shù)前端的根本區(qū)別在于,基本前端需要函數(shù)指針,而函數(shù)前端讓你使用函數(shù)對象。
第三個前端稱為 eUML,它基于特定領(lǐng)域的語言。該前端可以通過重用 UML 狀態(tài)機的定義來定義狀態(tài)機。熟悉 UML 的開發(fā)人員可以將 UML 行為圖中的定義復(fù)制到 C++ 代碼。您不需要將 UML 定義轉(zhuǎn)換為 C++ 代碼。
eUML 基于您必須與此前端一起使用的一組宏。宏的優(yōu)點是您不需要直接使用 Boost.MetaStateMachine 提供的許多類。您只需要知道要使用哪些宏。這意味著您不能忘記從類派生狀態(tài)機,這可能發(fā)生在基本前端或函數(shù)前端。本章介紹使用 eUML 的 Boost.MetaStateMachine。
二、示例和代碼
示例 68.1。使用 eUML 的簡單狀態(tài)機
#include <boost/msm/front/euml/euml.hpp> #include <boost/msm/front/euml/state_grammar.hpp> #include <boost/msm/back/state_machine.hpp> #include <iostream> namespace msm = boost::msm; using namespace boost::msm::front::euml; BOOST_MSM_EUML_STATE((), Off) BOOST_MSM_EUML_STATE((), On) BOOST_MSM_EUML_EVENT(press) BOOST_MSM_EUML_TRANSITION_TABLE(( Off + press == On, On + press == Off ), light_transition_table) BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (light_transition_table, init_ << Off), light_state_machine) int main() { msm::back::state_machine<light_state_machine> light; std::cout << *light.current_state() << '\n'; light.process_event(press); std::cout << *light.current_state() << '\n'; light.process_event(press); std::cout << *light.current_state() << '\n'; }
示例 68.1 使用了最簡單的狀態(tài)機:一盞燈恰好有兩種狀態(tài)。它可以打開或關(guān)閉。如果它是關(guān)閉的,它可以被打開。如果已打開,則可以將其關(guān)閉??梢詮拿總€狀態(tài)切換到每個其他狀態(tài)。
示例 68.1 使用 eUML 前端來描述燈的狀態(tài)機。 Boost.MetaStateMachine 沒有主頭文件。因此,必須將需要的頭文件一一包含進(jìn)來。 boost/msm/front/euml/euml.hpp 和 boost/msm/front/euml/state_grammar.hpp 提供對 eUML 宏的訪問。 boost/msm/back/state_machine.hpp 需要將前端的狀態(tài)機鏈接到后端的狀態(tài)機。雖然前端提供了定義狀態(tài)機的各種可能性,但狀態(tài)機的實際實現(xiàn)是在后端找到的。由于 Boost.MetaStateMachine 僅包含一個后端,因此您無需選擇實現(xiàn)。
Boost.MetaStateMachine 中的所有定義都在命名空間 boost::msm 中。不幸的是,許多 eUML 宏并沒有明確引用這個命名空間中的類。他們使用命名空間 msm 或根本不使用命名空間。這就是為什么示例 68.1 為命名空間 boost::msm 創(chuàng)建了一個別名,并使 boost::msm::front::euml 中的定義可用于 using 指令。否則 eUML 宏會導(dǎo)致編譯器錯誤。
要使用燈的狀態(tài)機,首先要定義關(guān)和開的狀態(tài)。狀態(tài)是用宏 BOOST_MSM_EUML_STATE 定義的,它需要狀態(tài)的名稱作為它的第二個參數(shù)。第一個參數(shù)描述狀態(tài)。稍后你會看到這些描述是什么樣子的。示例 68.1 中定義的兩個狀態(tài)稱為關(guān)閉和打開。
要在狀態(tài)之間切換,需要事件。事件是用宏 BOOST_MSM_EUML_EVENT 定義的,它期望事件的名稱作為其唯一參數(shù)。示例 68.1 定義了一個名為 press 的事件,它表示按下電燈開關(guān)的動作。由于同一事件會打開和關(guān)閉一盞燈,因此只定義了一個事件。
定義所需的狀態(tài)和事件后,宏 BOOST_MSM_EUML_TRANSITION_TABLE 用于創(chuàng)建轉(zhuǎn)換表。該表定義了狀態(tài)之間的有效轉(zhuǎn)換以及哪些事件觸發(fā)了哪些狀態(tài)轉(zhuǎn)換。
BOOST_MSM_EUML_TRANSITION_TABLE 需要兩個參數(shù)。第一個參數(shù)定義了轉(zhuǎn)換表,第二個是轉(zhuǎn)換表的名稱。第一個參數(shù)的語法旨在使識別狀態(tài)和事件如何相互關(guān)聯(lián)變得容易。例如,Off + press == On 表示處于 Off 狀態(tài)的機器通過按下事件切換到 On 狀態(tài)。轉(zhuǎn)換表定義的直觀和不言自明的語法是 eUML 前端的優(yōu)勢之一。
創(chuàng)建轉(zhuǎn)換表后,使用宏 BOOST_MSM_EUML_DECLARE_STATE_MACHINE 定義狀態(tài)機。第二個參數(shù)也是更簡單的一個:它設(shè)置狀態(tài)機的名稱。示例 68.1 中的狀態(tài)機名為 light_state_machine。
BOOST_MSM_EUML_DECLARE_STATE_MACHINE 的第一個參數(shù)是一個元組。第一個值是轉(zhuǎn)換表的名稱。第二個值是一個使用 init_ 的表達(dá)式,它是 Boost.MetaStateMachine 提供的一個屬性。稍后您將了解有關(guān)屬性的更多信息。需要表達(dá)式 init_ << Off 將狀態(tài)機的初始狀態(tài)設(shè)置為 Off。
用 BOOST_MSM_EUML_DECLARE_STATE_MACHINE 定義的狀態(tài)機 light_state_machine 是一個類。您使用此類從后端實例化狀態(tài)機。在示例 68.1 中,這是通過將 light_state_machine 作為參數(shù)傳遞給類模板 boost::msm::back::state_machine 來完成的。這會創(chuàng)建一個名為 light 的狀態(tài)機。
狀態(tài)機提供一個成員函數(shù) process_event() 來處理事件。如果您將事件傳遞給 process_event(),狀態(tài)機會根據(jù)其轉(zhuǎn)換表更改其狀態(tài)。
為了更容易看到多次調(diào)用 process_event() 時示例 68.1 中發(fā)生的情況,調(diào)用了 current_state()。此成員函數(shù)應(yīng)僅用于調(diào)試目的。它返回一個指向 int 的指針。每個狀態(tài)都是一個 int 值,按照狀態(tài)在 BOOST_MSM_EUML_TRANSITION_TABLE 中被訪問的順序分配。在示例 68.1 中,Off 被賦予值 0,而 On 被賦予值 1。該示例將 0、1 和 0 寫入標(biāo)準(zhǔn)輸出。按下燈開關(guān)兩次,可以打開和關(guān)閉燈。
示例 68.2。具有狀態(tài)、事件和動作的狀態(tài)機
#include <boost/msm/front/euml/euml.hpp> #include <boost/msm/front/euml/state_grammar.hpp> #include <boost/msm/back/state_machine.hpp> #include <iostream> namespace msm = boost::msm; using namespace boost::msm::front::euml; BOOST_MSM_EUML_STATE((), Off) BOOST_MSM_EUML_STATE((), On) BOOST_MSM_EUML_EVENT(press) BOOST_MSM_EUML_ACTION(switch_light) { template <class Event, class Fsm> void operator()(const Event &ev, Fsm &fsm, BOOST_MSM_EUML_STATE_NAME(Off) &sourceState, BOOST_MSM_EUML_STATE_NAME(On) &targetState) const { std::cout << "Switching on\n"; } template <class Event, class Fsm> void operator()(const Event &ev, Fsm &fsm, decltype(On) &sourceState, decltype(Off) &targetState) const { std::cout << "Switching off\n"; } }; BOOST_MSM_EUML_TRANSITION_TABLE(( Off + press / switch_light == On, On + press / switch_light == Off ), light_transition_table) BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (light_transition_table, init_ << Off), light_state_machine) int main() { msm::back::state_machine<light_state_machine> light; light.process_event(press); light.process_event(press); }
示例 68.2 通過一個動作擴(kuò)展了燈的狀態(tài)機。動作由觸發(fā)狀態(tài)轉(zhuǎn)換的事件執(zhí)行。因為動作是可選的,所以可以在沒有它們的情況下定義狀態(tài)機。
操作是使用 BOOST_MSM_EUML_ACTION 定義的。嚴(yán)格來說,定義了一個函數(shù)對象。您必須重載運算符 operator()。操作員必須接受四個參數(shù)。參數(shù)引用一個事件、一個狀態(tài)機和兩個狀態(tài)。您可以自由定義模板或為所有參數(shù)使用具體類型。在示例 68.2 中,僅為最后兩個參數(shù)設(shè)置具體類型。因為這些參數(shù)描述了開始和結(jié)束狀態(tài),所以您可以重載 operator() 以便為不同的開關(guān)執(zhí)行不同的成員函數(shù)。
請注意狀態(tài) On 和 Off 是對象。 Boost.MetaStateMachine 提供了一個宏 BOOST_MSM_EUML_STATE_NAME 來獲取狀態(tài)的類型。如果您使用 C++11,則可以使用運算符 decltype 而不是宏。
switch_light 動作已通過 BOOST_MSM_EUML_ACTION 定義,在按下燈開關(guān)時執(zhí)行。轉(zhuǎn)換表已相應(yīng)更改。第一個轉(zhuǎn)換現(xiàn)在是 Off + press / switch_light == On。您在事件后的斜線后傳遞操作。此轉(zhuǎn)換意味著如果當(dāng)前狀態(tài)為 Off 并且事件按下發(fā)生,則調(diào)用 switch_light 的運算符 operator()。執(zhí)行操作后,新狀態(tài)為開啟。
示例 68.2 將 Switching on 然后 Switching off 寫入標(biāo)準(zhǔn)輸出。
示例 68.3。具有狀態(tài)、事件、守衛(wèi)和動作的狀態(tài)機
#include <boost/msm/front/euml/euml.hpp> #include <boost/msm/front/euml/state_grammar.hpp> #include <boost/msm/back/state_machine.hpp> #include <iostream> namespace msm = boost::msm; using namespace boost::msm::front::euml; BOOST_MSM_EUML_STATE((), Off) BOOST_MSM_EUML_STATE((), On) BOOST_MSM_EUML_EVENT(press) BOOST_MSM_EUML_ACTION(is_broken) { template <class Event, class Fsm, class Source, class Target> bool operator()(const Event &ev, Fsm &fsm, Source &src, Target &trg) const { return true; } }; BOOST_MSM_EUML_ACTION(switch_light) { template <class Event, class Fsm, class Source, class Target> void operator()(const Event &ev, Fsm &fsm, Source &src, Target &trg) const { std::cout << "Switching\n"; } }; BOOST_MSM_EUML_TRANSITION_TABLE(( Off + press [!is_broken] / switch_light == On, On + press / switch_light == Off ), light_transition_table) BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (light_transition_table, init_ << Off), light_state_machine) int main() { msm::back::state_machine<light_state_machine> light; light.process_event(press); light.process_event(press); }
示例 68.3 在轉(zhuǎn)換表中使用了一個守衛(wèi)。第一個轉(zhuǎn)換的定義是 Off + press [!is_broken] / switch_light == On。在括號中傳遞 is_broken 意味著狀態(tài)機在調(diào)用動作 switch_light 之前檢查是否可能發(fā)生轉(zhuǎn)換。這叫做守衛(wèi)。守衛(wèi)必須返回布爾類型的結(jié)果。
像 is_broken 這樣的守衛(wèi)是用 BOOST_MSM_EUML_ACTION 定義的,其方式與動作相同。因此,必須為相同的四個參數(shù)重載運算符 operator()。 operator() 必須有一個 bool 類型的返回值才能用作守衛(wèi)。
請注意,您可以使用運算符等邏輯運算符!在括號內(nèi)的守衛(wèi)上。
如果運行該示例,您會注意到?jīng)]有任何內(nèi)容寫入標(biāo)準(zhǔn)輸出。 switch_light 動作未執(zhí)行 - 燈保持關(guān)閉狀態(tài)。守衛(wèi) is_broken 返回 true。但是,因為運算符運算符!使用時,括號中的表達(dá)式的計算結(jié)果為 false。
您可以使用守衛(wèi)來檢查是否可以發(fā)生狀態(tài)轉(zhuǎn)換。示例 68.3 使用 is_broken 檢查燈是否壞了。雖然從關(guān)閉到打開的轉(zhuǎn)換通常是可能的,并且轉(zhuǎn)換表正確地描述了燈,但在此示例中,燈無法打開。盡管調(diào)用了兩次 process_event(),但燈的狀態(tài)為關(guān)閉。
示例 68.4。具有狀態(tài)、事件、進(jìn)入動作和退出動作的狀態(tài)機
#include <boost/msm/front/euml/euml.hpp> #include <boost/msm/front/euml/state_grammar.hpp> #include <boost/msm/back/state_machine.hpp> #include <iostream> namespace msm = boost::msm; using namespace boost::msm::front::euml; BOOST_MSM_EUML_ACTION(state_entry) { template <class Event, class Fsm, class State> void operator()(const Event &ev, Fsm &fsm, State &state) const { std::cout << "Entering\n"; } }; BOOST_MSM_EUML_ACTION(state_exit) { template <class Event, class Fsm, class State> void operator()(const Event &ev, Fsm &fsm, State &state) const { std::cout << "Exiting\n"; } }; BOOST_MSM_EUML_STATE((state_entry, state_exit), Off) BOOST_MSM_EUML_STATE((state_entry, state_exit), On) BOOST_MSM_EUML_EVENT(press) BOOST_MSM_EUML_TRANSITION_TABLE(( Off + press == On, On + press == Off ), light_transition_table) BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (light_transition_table, init_ << Off), light_state_machine) int main() { msm::back::state_machine<light_state_machine> light; light.process_event(press); light.process_event(press); }
在示例 68.4 中,傳遞給 BOOST_MSM_EUML_STATE 的第一個參數(shù)是一個由 state_entry 和 state_exit 組成的元組。 state_entry 是進(jìn)入動作,state_exit 是退出動作。這些動作在進(jìn)入或退出狀態(tài)時執(zhí)行。
與操作一樣,進(jìn)入和退出操作是使用 BOOST_MSM_EUML_ACTION 定義的。但是,重載運算符 operator() 只需要三個參數(shù):對事件的引用、狀態(tài)機和狀態(tài)。狀態(tài)之間的轉(zhuǎn)換對于進(jìn)入和退出操作無關(guān)緊要,因此只需將一個狀態(tài)傳遞給 operator()。對于進(jìn)入動作,進(jìn)入該狀態(tài)。對于退出操作,此狀態(tài)已退出。
在示例 68.4 中,狀態(tài) Off 和 On 都有進(jìn)入和退出操作。因為事件按下發(fā)生了兩次,所以 Entering 和 Exiting 顯示了兩次。請注意,Exiting 會先顯示,Entering 會顯示在后面,因為執(zhí)行的第一個操作是退出操作。
第一個事件按下觸發(fā)從關(guān)閉到開啟的轉(zhuǎn)換,退出和進(jìn)入各顯示一次。第二次事件按下將狀態(tài)切換為關(guān)閉。 Exiting 和 Entering 再次顯示一次。因此,狀態(tài)轉(zhuǎn)換首先執(zhí)行退出動作,然后執(zhí)行新狀態(tài)的進(jìn)入動作。
示例 68.5。狀態(tài)機中的屬性
#include <boost/msm/front/euml/euml.hpp> #include <boost/msm/front/euml/state_grammar.hpp> #include <boost/msm/back/state_machine.hpp> #include <iostream> namespace msm = boost::msm; using namespace boost::msm::front::euml; BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int, switched_on) BOOST_MSM_EUML_ACTION(state_entry) { template <class Event, class Fsm, class State> void operator()(const Event &ev, Fsm &fsm, State &state) const { std::cout << "Switched on\n"; ++fsm.get_attribute(switched_on); } }; BOOST_MSM_EUML_ACTION(is_broken) { template <class Event, class Fsm, class Source, class Target> bool operator()(const Event &ev, Fsm &fsm, Source &src, Target &trg) const { return fsm.get_attribute(switched_on) > 1; } }; BOOST_MSM_EUML_STATE((), Off) BOOST_MSM_EUML_STATE((state_entry), On) BOOST_MSM_EUML_EVENT(press) BOOST_MSM_EUML_TRANSITION_TABLE(( Off + press [!is_broken] == On, On + press == Off ), light_transition_table) BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (light_transition_table, init_ << Off, no_action, no_action, attributes_ << switched_on), light_state_machine) int main() { msm::back::state_machine<light_state_machine> light; light.process_event(press); light.process_event(press); light.process_event(press); light.process_event(press); light.process_event(press); }
示例 68.5 使用守衛(wèi) is_broken 檢查是否可以從 Off 到 On 的狀態(tài)轉(zhuǎn)換。這次 is_broken 的返回值取決于電燈開關(guān)被按下的頻率??梢栽跓魤闹皩舸蜷_兩次。為了計算燈打開的頻率,使用了一個屬性。
屬性是可以附加到對象的變量。它們允許您在運行時調(diào)整狀態(tài)機的行為。因為諸如開燈頻率之類的數(shù)據(jù)必須存儲在某個地方,所以將其直接存儲在狀態(tài)機、狀態(tài)或事件中是有意義的。
在使用屬性之前,必須對其進(jìn)行定義。這是通過宏 BOOST_MSM_EUML_DECLARE_ATTRIBUTE 完成的。傳遞給 BOOST_MSM_EUML_DECLARE_ATTRIBUTE 的第一個參數(shù)是類型,第二個是屬性的名稱。示例 68.5 定義了 int 類型的屬性 switched_on。
定義屬性后,必須將其附加到對象。該示例將屬性 switched_on 附加到狀態(tài)機。這是通過元組中的第五個值完成的,該值作為第一個參數(shù)傳遞給 BOOST_MSM_EUML_DECLARE_STATE_MACHINE。使用 attributes_,來自 Boost.MetaStateMachine 的關(guān)鍵字用于創(chuàng)建 lambda 函數(shù)。要將屬性 switched_on 附加到狀態(tài)機,請使用 operator<< 將 switched_on 寫入 attributes_,就好像它是一個流一樣。
元組中的第三個和第四個值都設(shè)置為 no_action。該屬性作為元組中的第五個值傳遞。第三個和第四個值可用于定義狀態(tài)機的進(jìn)入和退出操作。如果沒有定義進(jìn)入和退出操作,請使用 no_action。
將屬性附加到狀態(tài)機后,可以使用 get_attribute() 訪問它。在示例 68.5 中,此成員函數(shù)在入口操作 state_entry 中被調(diào)用以增加屬性的值。因為 state_entry 僅鏈接到狀態(tài) On,switched_on 僅在燈打開時遞增。
switched_on 也可以從守衛(wèi) is_broken 訪問,它檢查屬性的值是否大于 1。如果是,守衛(wèi)返回 true。由于屬性是使用默認(rèn)構(gòu)造函數(shù)初始化的,并且 switched_on 設(shè)置為 0,如果燈已打開兩次,is_broken 將返回 true。
在示例 68.5 中,事件按下發(fā)生了五次。燈被打開和關(guān)閉兩次,然后再次打開。燈打開的前兩次會顯示“已打開”。但是,第三次打開燈時沒有輸出。發(fā)生這種情況是因為 is_broken 在燈被打開兩次后返回 true,因此,沒有從 Off 到 On 的狀態(tài)轉(zhuǎn)換。這意味著不執(zhí)行狀態(tài) On 的進(jìn)入操作,并且該示例不寫入標(biāo)準(zhǔn)輸出。
示例 68.6。訪問轉(zhuǎn)換表中的屬性
#include <boost/msm/front/euml/euml.hpp> #include <boost/msm/front/euml/state_grammar.hpp> #include <boost/msm/back/state_machine.hpp> #include <iostream> namespace msm = boost::msm; using namespace boost::msm::front::euml; BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int, switched_on) void write_message() { std::cout << "Switched on\n"; } BOOST_MSM_EUML_FUNCTION(WriteMessage_, write_message, write_message_, void, void) BOOST_MSM_EUML_STATE((), Off) BOOST_MSM_EUML_STATE((), On) BOOST_MSM_EUML_EVENT(press) BOOST_MSM_EUML_TRANSITION_TABLE(( Off + press [fsm_(switched_on) < Int_<2>()] / (++fsm_(switched_on), write_message_()) == On, On + press == Off ), light_transition_table) BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (light_transition_table, init_ << Off, no_action, no_action, attributes_ << switched_on), light_state_machine) int main() { msm::back::state_machine<light_state_machine> light; light.process_event(press); light.process_event(press); light.process_event(press); light.process_event(press); light.process_event(press); }
示例 68.6 與示例 68.5 做同樣的事情:將燈打開兩次后,燈壞了,無法再打開。雖然前面的示例在操作中訪問了 switched_on 屬性,但此示例使用轉(zhuǎn)換表中的屬性。
Boost.MetaStateMachine 提供函數(shù) fsm_() 來訪問狀態(tài)機中的屬性。這樣就定義了一個守衛(wèi)來檢查 switched_on 是否小于 2。并且定義了一個動作,每次狀態(tài)從 Off 切換到 On 時都會增加 switched_on。
請注意,守衛(wèi)中的小于比較是通過 Int_<2>() 完成的。數(shù)字 2 必須作為模板參數(shù)傳遞給 Int_ 以創(chuàng)建此類的實例。這將創(chuàng)建一個具有 Boost.MetaStateMachine 所需類型的函數(shù)對象。
示例 68.6 還使用宏 BOOST_MSM_EUML_FUNCTION 使函數(shù)成為動作。傳遞給 BOOST_MSM_EUML_FUNCTION 的第一個參數(shù)是可以在函數(shù)前端使用的動作的名稱。第二個參數(shù)是函數(shù)的名稱。第三個參數(shù)是在 eUML 中使用的操作名稱。第四個和第五個參數(shù)是函數(shù)的返回值——一個用于動作用于狀態(tài)轉(zhuǎn)換的情況,另一個用于動作描述進(jìn)入或退出動作的情況。以這種方式將 write_message() 轉(zhuǎn)換為動作后,將在轉(zhuǎn)換表中的 ++fsm_(switched_on) 之后創(chuàng)建并使用 write_message_ 類型的對象。在從 Off 到 On 的狀態(tài)轉(zhuǎn)換中,屬性 switched_on 遞增,然后調(diào)用 write_message()。
與示例 68.5 中一樣,示例 68.6 顯示兩次打開。
Boost.MetaStateMachine 提供額外的函數(shù),例如 state_() 和 event_(),以訪問附加到其他對象的屬性。其他類,例如 Char_ 和 String_,也可以像 Int_ 一樣使用。
提示
正如您在示例中看到的,前端 eUML 要求您使用許多宏。頭文件 boost/msm/front/euml/common.hpp 包含所有 eUML 宏的定義,這使其成為一個有用的參考。
練習(xí)
為可以關(guān)閉、打開或傾斜的窗口創(chuàng)建狀態(tài)機。關(guān)閉的窗戶可以打開或傾斜。如果不先關(guān)閉打開的窗戶,則無法傾斜它。傾斜的窗戶也不能在不先關(guān)閉的情況下打開。通過打開和傾斜您的窗口幾次來測試您的狀態(tài)機。使用 current_state() 將狀態(tài)寫入標(biāo)準(zhǔn)輸出。
擴(kuò)展?fàn)顟B(tài)機:窗戶應(yīng)該是智能家居的一部分。狀態(tài)機現(xiàn)在應(yīng)該計算窗戶打開和傾斜的頻率。要測試您的狀態(tài)機,請打開并傾斜您的窗口幾次。在程序結(jié)束時,將窗口打開的頻率和傾斜的頻率寫入標(biāo)準(zhǔn)輸出。
到此這篇關(guān)于C++ Boost MetaStateMachine定義狀態(tài)機超詳細(xì)講解的文章就介紹到這了,更多相關(guān)C++ Boost MetaStateMachine內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
OpenCV4.1.0+VisualStudio2019開發(fā)環(huán)境搭建(超級簡單)
這篇文章主要介紹了OpenCV4.1.0+VisualStudio2019開發(fā)環(huán)境搭建(超級簡單),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03C語言數(shù)據(jù)結(jié)構(gòu)之線索二叉樹及其遍歷
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之線索二叉樹及其遍歷的相關(guān)資料,為了加快查找節(jié)點的前驅(qū)和后繼。對二叉樹的線索化就是對二叉樹進(jìn)行一次遍歷,在遍歷的過程中檢測節(jié)點的左右指針是否為空,如果是空,則將他們改為指向前驅(qū)和后繼節(jié)點的線索,需要的朋友可以參考下2017-08-08c++ 獲取數(shù)字字符串的子串?dāng)?shù)值性能示例分析
這篇文章主要為大家介紹了c++ 獲取數(shù)字字符串的子串?dāng)?shù)值示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11如何基于 Blueprint 在游戲中創(chuàng)建實時音視頻功能
我們在本文先來講講如何在 Unreal 中用 Blueprint 快速實現(xiàn)。稍后會分享基于 C++的實現(xiàn)步驟。感興趣的朋友跟隨小編一起看看吧2020-05-05C/C++?Qt?TableDelegate?自定義代理組件使用詳解
TableDelegate自定義代理組件的主要作用是對原有表格進(jìn)行調(diào)整,本文主要介紹了QT中TableDelegate?自定義代理組件的使用教程,感興趣的朋友可以了解一下2021-12-12