CPP魔法之编译期FSM

Akano 发布于 2025-12-31 15 次阅读


尝试为嵌入式写一个编译期FSM

#include <initializer_list>
#include <array>
#include <cstdint>

namespace FsmSpace{
using StateType = uint16_t;
using ExecFuncPtr  = void(*)(void);
using TransFuncPtr = bool(*)(void);
template<auto _state,ExecFuncPtr _exec>
struct ExecType{
	static constexpr StateType state = static_cast<StateType>(_state);
	static constexpr ExecFuncPtr exec  = _exec;
};
template<auto _stateIn,auto _stateOut,TransFuncPtr _transFunc>
struct TransType{
	static constexpr StateType stateIn = static_cast<StateType>(_stateIn);
	static constexpr StateType stateOut = static_cast<StateType>(_stateOut);
	static constexpr TransFuncPtr transFunc  = _transFunc;
};
template<class... func>struct Pack;
template<StateType maxState,class Execs,class Trans>class FSM;


template<StateType maxState,class... ExecEntries,class... Trans>
class FSM<maxState,Pack<ExecEntries...>,Pack<Trans...> >{
private:
	static constexpr std::size_t exec_count  = sizeof...(ExecEntries);
	static constexpr std::size_t trans_count = sizeof...(Trans);
	struct TransItem{
		StateType in;
		StateType out;
		TransFuncPtr func;
	};
	inline static constexpr std::array<ExecFuncPtr,maxState + 1> exec_arr = []{
		std::array<ExecFuncPtr,maxState + 1> ret{};
		(void)std::initializer_list<int>{
			((ret[ExecEntries::state] = ExecEntries::exec),0)...
		};
		return ret;
	}();
	inline static constexpr std::array<TransItem,trans_count> trans_arr{
		TransItem{Trans::stateIn,Trans::stateOut,Trans::transFunc}...
	};
	StateType now_state;
public:
	FSM() = delete;
	template<typename enumT>
	FSM(enumT default_state){
		//TODO:static assert to ensure enumT is correct
		now_state = static_cast<StateType>(default_state);
	}
	void execute(){
		if(exec_arr[now_state] != nullptr)exec_arr[now_state]();
		return ;
	}
	void trans(){
		for(const auto& trans : trans_arr){
			if(now_state == trans.in && trans.func != nullptr && trans.func()){
				now_state = trans.out;
				return ;
			}
		}
		return ;
	}
	void update(){
		trans();
		execute();
		return ;
	}
	template<typename enumT>
	void setState(enumT new_state){
		//TODO:static assert to ensure enumT is correct
		now_state = static_cast<StateType>(new_state);
		return ;
	}
	StateType getState(){
		return now_state;
	}
	bool validate(){
		uint8_t cnt = 0;
		for(const auto& trans : trans_arr){
			if(now_state == trans.in && trans.func != nullptr && trans.func()){
				cnt++;
			}
		}
		return (cnt <= 1);
	}
};
}//FsmSpace
此作者没有提供个人介绍。
最后更新于 2026-09-10