Last active
August 29, 2015 14:22
-
-
Save unix-beard/558bb51c49f3b0544617 to your computer and use it in GitHub Desktop.
Template-based state machine (prototype)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <tuple> | |
#include <type_traits> | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// TBD: | |
// Recursively find the start state at compile time and make static_assert fail if one is not found | |
// (also terminate the recursive search as soon as the start state is found). | |
// Do the same of the end state but don't make static_assert fail, since a state machine is allowed not to have one. | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
struct state { virtual void operator()() const = 0; }; | |
struct start_state : state {}; | |
struct end_state : state {}; | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Checks whether T is of start_state type. Provides the member constant value that is equal to true, | |
// if T is of start_state type. Otherwise, value is equal to false. | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
template<class T> | |
struct is_start_state : std::is_base_of<start_state, T> | |
{}; | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Find the start state | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
template<class T, int S> | |
struct FindStartState | |
{ | |
template<class U, int N> | |
static typename std::enable_if<is_start_state<U>::value, U>::type get_start_state() | |
{ | |
return U(); | |
} | |
template<class U, int N> | |
static typename std::enable_if<!is_start_state<U>::value, U>::type get_start_state() | |
{ | |
static_assert(N >= 0, "No start state found"); | |
return get_start_state<U, N - 1>(); | |
} | |
static T start_state; | |
}; | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Out-of-class definition of the FindStartState static data-member | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
template<class T, int S> T FindStartState<T, S>::start_state = FindStartState::get_start_state<T, S>(); | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
template<class FromState, int... Ts> | |
class state_trans | |
{ | |
public: | |
FromState from_state; | |
}; | |
template<class... Trans> | |
class state_machine | |
{ | |
public: | |
state_machine() | |
{ | |
//find_start_state<sizeof...(Trans) - 1>(); | |
build_states_tuple<decltype(transitions), sizeof...(Trans) - 1>(transitions); | |
} | |
void run() { (*start)(); } | |
private: | |
template<int N> | |
void find_start_state() | |
{ | |
using state_type = decltype(std::get<N>(transitions).from_state); | |
start = &FindStartState<state_type, N>::start_state; | |
} | |
template<class StateTransTuple, size_t N> | |
void build_states_tuple(StateTransTuple& t) | |
{ | |
auto d = std::get<N>(t).from_state; | |
} | |
std::tuple<Trans...> transitions; | |
start_state* start; | |
}; | |
/*********************************************************************************************************************** | |
* Start state | |
**********************************************************************************************************************/ | |
struct my_state1 : start_state { void operator()() const override { std::cout << __PRETTY_FUNCTION__ << "\n"; } }; | |
/*********************************************************************************************************************** | |
* Regular state | |
**********************************************************************************************************************/ | |
struct my_state2 : state { void operator()() const override { std::cout << __PRETTY_FUNCTION__ << "\n"; } }; | |
/*********************************************************************************************************************** | |
* End state | |
**********************************************************************************************************************/ | |
struct my_state3 : end_state { void operator()() const override { std::cout << __PRETTY_FUNCTION__ << "\n"; } }; | |
int main() | |
{ | |
state_machine< | |
/* ===================== State transition table ================*/ | |
/* state_trans<my_state1, my_state2, my_state3>, */ | |
state_trans<my_state1, 0, 1, 0 >, | |
state_trans<my_state2, 0, 0, 1 >, | |
state_trans<my_state3, 0, 0, 0 > | |
/* ===================== State transition table ================*/ | |
> sm; | |
//sm.run(); | |
//FindStartState<my_state1, 2>::start_state(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment