0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

状態遷移をenum classを使って書く

Last updated at Posted at 2022-07-18

enum classを使って状態遷移を記述しました。特徴は以下になります。

  • c++11以降
  • 状態(State)をenum classを使って定義する。値を指定しているが、コーディングで意識する必要はなし。
  • 遷移(Transition)をStateからこちらもenuma class を使って定義する。constexprでStateの値を元にする。
  • unionを使って遷移前Stateと遷移後Stateを使って今回のTransition値を導く
  • TransitionIdが決まるので、switchはenum classの要素を指定できる

ソースコード

main

main.cxx
namespace StateMachine {
  enum class State : uint8_t {
  	NoState = 0,
    Idle = 1,
    Wait = 2,
    Running = 3,
	};
	constexpr uint16_t makeTransitionId(State from, State to) {
		return static_cast<uint16_t>(from) | static_cast<uint16_t>(to) << 8;
	}
	enum class Transition : uint16_t {
		NoState_Idle = makeTransitionId(State::NoState, State::Idle),
		Idle_NoState = makeTransitionId(State::Idle, State::NoState),
		Idle_Wait = makeTransitionId(State::Idle, State::Wait),
		Wait_Idle = makeTransitionId(State::Wait, State::Idle),
		Wait_Running = makeTransitionId(State::Wait, State::Running),
		Running_Wait = makeTransitionId(State::Running, State::Wait),
		Running_Idle = makeTransitionId(State::Running, State::Idle),
	};
	union convert_u {
		struct transition_t {
			State previous;
			State current;
		} state_;
		Transition transitionId;
	};
  void dispatch(State current) {
		static convert_u transition_ = {State::NoState, State::NoState};
		transition_.state_.previous = transition_.state_.current;
		transition_.state_.current = current;
		std::cout.setf(std::ios::hex, std::ios::basefield);
		std::cout << "TransitionId:" << static_cast<uint16_t>(transition_.transitionId);
		switch (transition_.transitionId) {
		case Transition::NoState_Idle:
			std::cout << ":NoState -> Idle" << std::endl;
			break;
		case Transition::Idle_Wait:
			std::cout << ":Idle -> Wait" << std::endl;
			break;
		case Transition::Wait_Idle:
			std::cout << ":Wait -> Idle" << std::endl;
			break;
		case Transition::Wait_Running:
			std::cout << ":Wait -> Running" << std::endl;
			break;
		case Transition::Running_Idle:
			std::cout << ":Running -> Idle" << std::endl;
			break;
		case Transition::Running_Wait:
			std::cout << ":Running -> Wait" << std::endl;
			break;
		case Transition::Idle_NoState:
			std::cout << ":Idle -> NoState" << std::endl;
			break;
		default:
			std::cout << ":Undefined" << std::endl;
			break;
	  }
	  std::cout << "prev. State:" << static_cast<uint16_t>(transition_.state_.previous) << " curr. State:" << static_cast<uint16_t>(transition_.state_.current) << std::endl;
  }
}
int main(int argc, char ** argv)
{
	StateMachine::dispatch(StateMachine::State::Idle);
	std::cout << "----------------------------------------" << std::endl;
	StateMachine::dispatch(StateMachine::State::Wait);
	std::cout << "----------------------------------------" << std::endl;
	StateMachine::dispatch(StateMachine::State::Running);
	std::cout << "----------------------------------------" << std::endl;
	StateMachine::dispatch(StateMachine::State::Idle);
	std::cout << "----------------------------------------" << std::endl;
	StateMachine::dispatch(StateMachine::State::Running);
	return 0;
}

Makefile

Makefile
TARG += enumclass
SRCS += main.cxx
OPTS += -g
FLAGS += -std=c++11 -Wno-unused-parameter -fno-strict-aliasing -fsanitize=address -fno-omit-frame-pointer
LIBDS += -L/usr/lib/llvm-10/lib -L/usr/include/lib

$(TARG): main.cxx
	clang++ $(SRCS) $(OPTS) $(FLAGS) $(INCS) $(LIBDS) $(LIBS) -o $(TARG)

実行結果

$ ./enumclass
----------------------------------------
TransitionId:100:NoState -> Idle
prev. State:0 curr. State:1
----------------------------------------
TransitionId:201:Idle -> Wait
prev. State:1 curr. State:2
----------------------------------------
TransitionId:302:Wait -> Running
prev. State:2 curr. State:3
----------------------------------------
TransitionId:103:Running -> Idle
prev. State:3 curr. State:1
----------------------------------------
TransitionId:301:Undefined
prev. State:1 curr. State:3
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?