尝试为嵌入式写一个编译期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

Comments NOTHING