ステートチャートのチュートリアルで説明されている状態内反応を見ましたか? あなたが探していることをしているようです。
あなたは代替案を求めているので、この期間に私はさまざまな C++ Harel ステートチャートの実装を評価しています。BoostステートチャートとBoost MSMを見ました。私は両方でコードを書きました。彼らは私の弱い脳を傷つけます:-)
それからMachine Objects (Macho)を見つけました。これは非常にシンプルで小さく、とても気に入っています。階層的なステート マシン、エントリ/エグジット アクション、履歴、ステート マシンのスナップショット、ガード、内部遷移、イベントの遅延、状態ローカル ストレージ (オプションの永続性を使用) をサポートしているため、私にとっては満足のいく Harel ステートチャートの実装です。
このコードは、ステートチャートの FunctionMode 部分を Macho で実装します。
#include "Macho.hpp"
#include <exception>
#include <iostream>
using namespace std;
namespace FunctionMode {
struct FunctionMode;
struct F1Mode;
struct F2Mode;
// The Top state, containing all the others.
TOPSTATE(Top) {
STATE(Top)
// All the events of the state machine are just virtual functions.
// Here we throw to mean that no inner state has implemented the event
// handler and we consider that an error. This is optional, we could
// just have an empty body or log the error.
virtual void evF1() { throw std::exception(); }
virtual void evF2() { throw std::exception(); }
// evF3 and so on...
private:
void init() { setState<FunctionMode>(); } // initial transition
};
SUBSTATE(FunctionMode, Top) {
STATE(FunctionMode)
virtual void evF1() { setState<F1Mode>(); }
virtual void evF2() { setState<F2Mode>(); }
// evF3, ...
private:
void entry() { cout << "FunctionMode::entry" << endl; }
void exit() { cout << "FunctionMode::exit" << endl; }
void init() { setState<F1Mode>(); } // initial transition
};
SUBSTATE(F1Mode, FunctionMode) {
STATE(F1Mode)
virtual void evF1() {} // make the event an internal transition (by swallowing it)
private:
void entry() { cout << "F1Mode::entry" << endl; }
void exit() { cout << "F1Mode::exit" << endl; }
};
SUBSTATE(F2Mode, FunctionMode) {
STATE(F2Mode)
virtual void evF2() {} // make the event an internal transition (by swallowing it)
private:
void entry() { cout << "F2Mode::entry" << endl; }
void exit() { cout << "F2Mode::exit" << endl; }
};
} // namespace FunctionMode
int main() {
Macho::Machine<FunctionMode::Top> sm;
// Now the machine is already in F1Mode.
// Macho has 2 methods for synchronous event dispatching:
// First method:
sm->evF1(); // <= this one will be swallowed by F1Mode::evF1()
// Second method:
sm.dispatch(Event(&FunctionMode::Top::evF2));
return 0;
}
それを実行すると、出力は次のようになります。
FunctionMode::entry
F1Mode::entry
F1Mode::exit
F2Mode::entry
F2Mode::exit
FunctionMode::exit
これは、トランジションが内部であることを示しています。
私の意見では、クリーンで簡単でコンパクトなコードです:-)
[EDIT1] コードの最初のバージョンは、最初の遷移を実行しませんでしたFunctionMode
-> F1Mode
. 今はそうです。