Skip to content

Instantly share code, notes, and snippets.

@unix-beard
Last active August 29, 2015 14:22
Show Gist options
  • Save unix-beard/558bb51c49f3b0544617 to your computer and use it in GitHub Desktop.
Save unix-beard/558bb51c49f3b0544617 to your computer and use it in GitHub Desktop.
Template-based state machine (prototype)
#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