Last active
August 29, 2015 14:16
-
-
Save wx257osn2/8cee1725d5275e9993ce to your computer and use it in GitHub Desktop.
ICE at Torino(VC++ Nov 2013 CTP)
This file contains 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
#pragma warning(disable:4592) | |
#pragma warning(disable:4425) | |
#pragma warning(disable:4503) | |
#include<utility> | |
#include<tuple> | |
#include<memory> | |
namespace temple{ | |
template<typename...>struct type_tuple; | |
template<typename T> | |
struct type_wrapper{using type = T;}; | |
template<typename>struct unwrap_impl; | |
template<template<typename>class Wrap, typename T> | |
struct unwrap_impl<Wrap<T>>{using type = T;}; | |
template<typename T> | |
using unwrap = typename unwrap_impl<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::type; | |
template<typename,typename>struct make_type_tuple_impl_impl; | |
template<typename... Lefts, typename... Rights> | |
struct make_type_tuple_impl_impl<type_tuple<Lefts...>, type_tuple<Rights...>>{ | |
using type = type_tuple<Lefts..., Rights...>; | |
}; | |
template<std::size_t N, typename T> | |
struct make_type_tuple_impl : | |
make_type_tuple_impl_impl< | |
typename make_type_tuple_impl< N/2, T>::type, | |
typename make_type_tuple_impl<N - N/2, T>::type | |
>{}; | |
template<typename T> | |
struct make_type_tuple_impl<1, T>{using type = type_tuple<T>;}; | |
template<typename T> | |
struct make_type_tuple_impl<0, T>{using type = type_tuple< >;}; | |
template<std::size_t N, typename T = void> | |
using make_type_tuple = typename make_type_tuple_impl<N, T>::type; | |
template<typename>struct type_at_impl_impl_impl; | |
template<typename... Types> | |
struct type_at_impl_impl_impl<type_tuple<Types...>>{template<typename T>static T eval(Types*..., T*, ...);}; | |
template<std::size_t N, typename... Types> | |
struct type_at_impl_impl{ | |
using type = decltype(type_at_impl_impl_impl<make_type_tuple<N>>::eval(static_cast<Types*>(nullptr)...)); | |
}; | |
template<typename T, std::size_t N> | |
class type_at_impl{ | |
template<template<typename...>class Type, class... Args> | |
static auto impl(type_wrapper<Type<Args...>>)->typename type_at_impl_impl<N, type_wrapper<Args>...>::type; | |
using temp = decltype(impl(type_wrapper<T>{})); | |
public: | |
using type = typename temp::type; | |
}; | |
template<typename T, std::size_t N> | |
using type_at = typename type_at_impl<typename std::remove_cv<typename std::remove_reference<T>::type>::type, N>::type; | |
template<typename>struct tuple_size_impl; | |
template<template<typename...>class Tuple, typename... Types> | |
struct tuple_size_impl<Tuple<Types...>>{ | |
static constexpr std::size_t value = sizeof...(Types); | |
constexpr operator std::size_t()const{return value;} | |
constexpr tuple_size_impl(){} | |
}; | |
template<typename T> | |
using tuple_size = tuple_size_impl<typename std::remove_cv<typename std::remove_reference<T>::type>::type>; | |
template<typename... Types> | |
struct type_tuple{ | |
template<std::size_t N> | |
using at = type_at<type_tuple<Types...>, N>; | |
static constexpr std::size_t size = sizeof...(Types); | |
}; | |
template<long long...>struct index_tuple; | |
template<typename>struct index_at_impl; | |
template<typename... Types> | |
struct index_at_impl<type_tuple<Types...>>{template<typename T>static constexpr T eval(Types..., T t, ...){return t;}}; | |
template<typename T, std::size_t N> | |
class index_at{ | |
template<template<long long...>class IndexTuple, long long... Indices> | |
static constexpr long long impl(IndexTuple<Indices...> t)noexcept{return index_at_impl<make_type_tuple<N, long long>>::eval(Indices...);} | |
public: | |
static constexpr long long value = impl(T{}); | |
constexpr operator long long()const noexcept{return value;} | |
}; | |
template<typename,long long>struct make_index_range_next; | |
template<long long... Indices, long long Next> | |
struct make_index_range_next<index_tuple<Indices...>, Next>{using type = index_tuple<Indices..., (Indices+Next)...>;}; | |
template<typename,long long,long long>struct make_index_range_next_; | |
template<long long... Indices, long long Next, long long Tail> | |
struct make_index_range_next_<index_tuple<Indices...>, Next, Tail>{using type = index_tuple<Indices..., (Indices+Next)..., Tail>;}; | |
template<long long,long long,long long,typename = void>struct make_index_range_impl; | |
template<long long Begin, long long Step, long long Next> | |
struct make_index_range_impl<Begin, Step, Next, typename std::enable_if<(Next==0 || Next==1)>::type>{ | |
using type = typename std::conditional<Next==0, index_tuple<>, index_tuple<Begin>>::type; | |
}; | |
template<long long Begin, long long Step, long long Next> | |
struct make_index_range_impl<Begin, Step, Next, typename std::enable_if<(Next>1)>::type>{ | |
using type = typename std::conditional<Next % 2, | |
typename make_index_range_next_< | |
typename make_index_range_impl<Begin, Step, Next/2>::type, | |
Begin + Next/2 * Step, | |
Begin + (Next-1) * Step | |
>::type, | |
typename make_index_range_next< | |
typename make_index_range_impl<Begin, Step, Next/2>::type, | |
Begin + Next/2 * Step | |
>::type | |
>::type; | |
}; | |
template<long long Begin, long long End, long long Step = (Begin<End ? 1 : -1)> | |
using make_index_range = typename make_index_range_impl<Begin, Step, (End - Begin + (Step>0 ? Step-1 : Step+1)) / Step>::type; | |
template<typename,typename>struct reverse_index_tuple_impl_impl; | |
template<long long... Indices, long long... IndicesIndices> | |
struct reverse_index_tuple_impl_impl<index_tuple<Indices...>, index_tuple<IndicesIndices...>>{ | |
using type = index_tuple<index_at<index_tuple<Indices...>, sizeof...(IndicesIndices) - 1 - IndicesIndices>::value...>; | |
}; | |
template<typename>struct reverse_index_tuple_impl; | |
template<long long... Indices> | |
struct reverse_index_tuple_impl<index_tuple<Indices...>> : | |
reverse_index_tuple_impl_impl<index_tuple<Indices...>, make_index_range<0,sizeof...(Indices)>>{}; | |
template<typename T> | |
using reverse_index_tuple = typename reverse_index_tuple_impl<T>::type; | |
template<typename... Types> | |
using make_indexes = make_index_range<0, sizeof...(Types)>; | |
template<typename... Types> | |
using make_reverse_indexes = make_index_range<sizeof...(Types)-1, -1>; | |
template<std::size_t,template<long long, long long>class,typename>struct index_tuple_Olog_operation; | |
template<std::size_t N, template<long long, long long>class Operation, long long V, long long... Args> | |
struct index_tuple_Olog_operation<N, Operation, index_tuple<V, Args...>>{ | |
private: | |
using Left = index_tuple_Olog_operation< (N-1)/2, Operation, index_tuple<Args...>>; | |
using Right = index_tuple_Olog_operation<(N-1)-(N-1)/2, Operation, typename Left::remaining>; | |
public: | |
using remaining = typename Right::remaining; | |
static const long long value = Operation<V, Operation<Left::value, Right::value>::value>::value; | |
}; | |
template<template<long long, long long>class Operation, long long T, long long U, long long V, long long... Args> | |
struct index_tuple_Olog_operation<3, Operation, index_tuple<T, U, V, Args...>>{ | |
using remaining = index_tuple<Args...>; | |
static const long long value = Operation<T, Operation<U, V>::value>::value; | |
}; | |
template<template<long long, long long>class Operation, long long T, long long U, long long... Args> | |
struct index_tuple_Olog_operation<2, Operation, index_tuple<T, U, Args...>>{ | |
using remaining = index_tuple<Args...>; | |
static const long long value = Operation<T, U>::value; | |
}; | |
template<template<long long, long long>class Operation, long long T, long long... Args> | |
struct index_tuple_Olog_operation<1, Operation, index_tuple<T, Args...>>{ | |
using remaining = index_tuple<Args...>; | |
static const long long value = T; | |
}; | |
template<template<long long, long long>class Operation> | |
struct index_tuple_Olog_operation<0, Operation, index_tuple<>>{ | |
using remaining = index_tuple<>; | |
static const long long value = Operation<0,0>::default_value; | |
}; | |
template<long long... Indices> | |
struct index_tuple{ | |
static constexpr std::size_t size()noexcept{return sizeof...(Indices);} | |
}; | |
} | |
using temple::unwrap; | |
using temple::type_at; | |
using temple::type_tuple; | |
using temple::index_at; | |
using temple::reverse_index_tuple; | |
using temple::make_index_range; | |
using temple::make_reverse_indexes; | |
using temple::make_indexes; | |
using temple::index_tuple; | |
template<typename... Args> | |
using tuple = std::tuple<Args...>; | |
#if 0 | |
namespace impl{ | |
template<long long A, long long B>struct add{static const long long value = A+B;static const long long default_value = 0;}; | |
template<typename...>struct unique_types_impl; | |
template<typename T, typename... Remaining, typename... Uniques> | |
struct unique_types_impl<type_tuple<T, Remaining...>, Uniques...>{ | |
static const bool value = temple::index_tuple_Olog_operation<sizeof...(Uniques),add,index_tuple<std::is_same<T, Uniques>::value...>>::value == 0; | |
using type = typename std::conditional<value,typename unique_types_impl<type_tuple<Remaining...>, Uniques..., T>::type, typename unique_types_impl<type_tuple<Remaining...>,Uniques...>::type>::type; | |
}; | |
template<typename... Uniques> | |
struct unique_types_impl<type_tuple<>, Uniques...>{using type = type_tuple<Uniques...>;}; | |
} | |
#else | |
namespace impl{ | |
struct duplicate_type; | |
template<long long A, long long B>struct add{static const long long value = A+B;static const long long default_value = 0;}; | |
template<typename...>struct unique_types_impl; | |
template<typename SourceType, typename Type>struct filter{using type = typename std::conditional<std::is_same<SourceType, Type>::value, duplicate_type, Type>::type;}; | |
template<typename T, typename... Remaining, typename... Uniques> | |
struct unique_types_impl<type_tuple<T, Remaining...>, Uniques...>{ | |
using type = typename unique_types_impl<type_tuple<typename filter<T, Remaining>::type...>, Uniques..., T>::type; | |
}; | |
template<typename... Remaining, typename... Uniques> | |
struct unique_types_impl<type_tuple<duplicate_type, Remaining...>, Uniques...>:unique_types_impl<type_tuple<Remaining...>, Uniques...>{}; | |
template<typename... Uniques> | |
struct unique_types_impl<type_tuple<>, Uniques...>{using type = type_tuple<Uniques...>;}; | |
} | |
#endif | |
template<typename T> | |
using unique_types = typename impl::unique_types_impl<T>::type; | |
//template<typename T, typename... Args, std::size_t... Indices> | |
//T make_impl(tuple<Args...>&& t, index_tuple<Indices...>){return T(std::forward<Args>(std::get<Indices>(t))...);} | |
template<typename T, typename... Args, std::size_t... Indices> | |
T make_impl(const tuple<Args...>& t, index_tuple<Indices...>){return T(std::get<Indices>(t)...);} | |
//template<typename T, typename... Args> | |
//T make(tuple<Args...>&& t){return make_impl<T>(std::forward<tuple<Args...>>(t), make_indexes<Args...>{});} | |
template<typename T, typename... Args> | |
T make(const tuple<Args...>& t){return make_impl<T>(t, make_indexes<Args...>{});} | |
namespace deus{ | |
namespace impl{ | |
struct none{}; | |
struct default_guard{ | |
template<typename T> | |
bool operator()(const T&)const{return true;} | |
}; | |
struct default_action{ | |
template<typename T> | |
void operator()(const T&)const{} | |
}; | |
template<typename>class event; | |
template<typename>struct state; | |
template<typename From, typename Event, typename To, typename Guard, typename Action> | |
struct transition{ | |
Guard g; | |
Action a; | |
transition(Guard&& g):g(std::forward<Guard>(g)){} | |
transition(Action&& a):a(std::forward<Action>(a)){} | |
transition(Guard&& g, Action&& a):g(std::forward<Guard>(g)), a(std::forward<Action>(a)){} | |
template<typename E> | |
bool guard(E&& ev)const{return g(std::forward<E>(ev));} | |
template<typename E> | |
void action(E&& ev)const{a(std::forward<E>(ev));} | |
}; | |
template<typename From, typename Event, typename To, typename Guard> | |
struct transition<From, Event, To, Guard, default_action>{ | |
Guard g; | |
transition(Guard&& g):g(std::forward<Guard>(g)){} | |
template<typename A> | |
transition<From, Event, To, Guard, A> operator/(A&& a)const{return transition<From, Event, To, Guard, A>(std::forward<Guard>(g), std::forward<A>(a));} | |
template<typename E> | |
bool guard(E&& ev)const{return g(std::forward<E>(ev));} | |
template<typename E> | |
void action(E&& ev)const{} | |
}; | |
template<typename From, typename Event, typename To> | |
struct transition<From, Event, To, default_guard, default_action>{ | |
template<typename A> | |
transition<From, Event, To, default_guard, A> operator/(A&& a)const{return transition<From, Event, To, default_guard, A>(std::forward<A>(a));} | |
template<typename E> | |
bool guard(E&& ev)const{return true;} | |
template<typename E> | |
void action(E&& ev)const{} | |
}; | |
template<typename State> | |
struct state{ | |
template<typename Action> | |
transition<none, none, State, default_guard, Action> operator/(Action&& a)const{return transition<none, none, State, default_guard, Action>(std::forward<Action>(a));} | |
transition<State, none, none, default_guard, default_action> operator--(int)const{return transition<State, none, none, default_guard, default_action>{};} | |
}; | |
template<typename Event, typename Guard> | |
class _guarded_event{ | |
Guard g; | |
class sysu{ | |
Guard g; | |
public: | |
template<typename G> | |
sysu(G&& g):g(std::forward<G>(g)){} | |
template<typename From> | |
friend transition<From, Event, none, Guard, default_action> operator-(transition<From, none, none, default_guard, default_action>&& s, sysu&& g){ | |
return transition<From, Event, none, Guard, default_action>{std::forward<sysu>(g).g}; | |
} | |
}; | |
public: | |
_guarded_event(Guard&& g):g(std::forward<Guard>(g)){} | |
sysu operator--(int)const{return sysu{g};} | |
}; | |
template<typename Event, typename... Args> | |
struct event_args_wrapper{tuple<Args...> args;}; | |
template<typename Event> | |
class event{ | |
struct sysu{ | |
template<typename From> | |
friend transition<From, Event, none, default_guard, default_action> operator-(transition<From, none, none, default_guard, default_action>&& s, sysu&&){ | |
return transition<From, Event, none, default_guard, default_action>{}; | |
} | |
}; | |
public: | |
sysu operator--(int)const{return sysu{};} | |
template<typename Guard> | |
_guarded_event<Event, Guard> operator[](Guard&& g)const{return _guarded_event<Event, Guard>(std::forward<Guard>(g));} | |
template<typename... Args> | |
event_args_wrapper<Event, Args...> operator()(Args&&... args)const{return event_args_wrapper<Event, Args...>{tuple<Args...>{std::forward<Args>(args)...}};} | |
}; | |
template<typename From, typename Event, typename To, typename Guard, typename Action> | |
inline transition<From, Event, To, Guard, Action> operator>(transition<From, Event, none, Guard, default_action>&& s, transition<none, none, To, default_guard, Action>&& e){ | |
return transition<From, Event, To, Guard, Action>{std::forward<Guard>(s.g), std::forward<Action>(e.a)}; | |
} | |
template<typename From, typename Event, typename To, typename Action> | |
inline transition<From, Event, To, default_guard, Action> operator>(transition<From, Event, none, default_guard, default_action>&& s, transition<none, none, To, default_guard, Action>&& e){ | |
return transition<From, Event, To, default_guard, Action>{std::forward<Action>(e.a)}; | |
} | |
template<typename From, typename Event, typename To, typename Guard> | |
inline transition<From, Event, To, Guard, default_action> operator>(transition<From, Event, none, Guard, default_action>&& s, const state<To>& e){ | |
return transition<From, Event, To, Guard, default_action>{std::forward<Guard>(s.g)}; | |
} | |
template<typename From, typename Event, typename To> | |
inline transition<From, Event, To, default_guard, default_action> operator>(transition<From, Event, none, default_guard, default_action>&& s, const state<To>& e){ | |
return transition<From, Event, To, default_guard, default_action>{}; | |
} | |
template<typename Statemachine> | |
class state_machine : public state<Statemachine>{ | |
using TransitionTable = typename Statemachine::transition_table; | |
TransitionTable tt; | |
using Statuses = typename TransitionTable::Statuses; | |
template<typename Status> | |
struct status_id{ | |
template<typename>class conversion; | |
template<typename... Types> | |
class conversion<type_tuple<Types...>>{ | |
using A = make_index_range<0, sizeof...(Types)>; | |
using B = index_tuple<std::is_same<Status,Types>::value...>; | |
template<typename,typename>struct impl; | |
template<long long... As, long long... Bs> | |
struct impl<index_tuple<As...>, index_tuple<Bs...>>{using type = index_tuple<((As+1ll)*Bs)...>;}; | |
public: | |
using type = typename impl<A,B>::type; | |
}; | |
static const long long value = temple::index_tuple_Olog_operation<Statuses::size,::impl::add,typename conversion<Statuses>::type>::value-1ll; | |
}; | |
class holder{ | |
struct base{}; | |
template<typename T> | |
struct derived : base{ | |
derived() : t(){} | |
T t; | |
}; | |
std::shared_ptr<base> impl; | |
long long state; | |
public: | |
holder(const holder&) = default; | |
holder(holder&&) = default; | |
template<template<typename>class Wrapper, typename T> | |
holder(Wrapper<T>&& t) : impl(new derived<T>()), state(status_id<T>::value){} | |
template<typename T, typename... Args> | |
void transit(Args&&... args){impl.reset();impl = std::make_shared<derived<T>>(std::forward<Args>(args)...);state = status_id<T>::value;} | |
friend bool operator==(const holder& lhs, long long rhs){return lhs.state == rhs;} | |
friend bool operator!=(const holder& lhs, long long rhs){return !(lhs == rhs);} | |
}state; | |
template<typename Event, std::size_t N = 0, bool = N != TransitionTable::size> | |
struct exec_events_{ | |
static void exec(holder& state, const TransitionTable& tt){ | |
using transition = type_at<TransitionTable,N>; | |
if(state == status_id<type_at<transition,0>>::value && (std::is_same<Event, type_at<transition,1>>::value || std::is_same<none, type_at<transition,1>>::value)){ | |
Event ev; | |
if(std::get<N>(tt.table).guard(ev)){ | |
std::get<N>(tt.table).action(ev); | |
if(state != status_id<type_at<transition,2>>::value) | |
state.template transit<type_at<transition,2>>(); | |
exec_events_<none, N+1>::exec(state, tt); | |
return; | |
} | |
} | |
exec_events_<Event, N+1>::exec(state, tt); | |
} | |
template<typename EventArgs> | |
static void exec(holder& state, const TransitionTable& tt, const EventArgs& args){ | |
using transition = type_at<TransitionTable,N>; | |
if(state == status_id<type_at<transition,0>>::value && (std::is_same<Event, type_at<transition,1>>::value || std::is_same<none, type_at<transition,1>>::value)){ | |
Event ev = make<Event>(args.args); | |
if(std::get<N>(tt.table).guard(ev)){ | |
std::get<N>(tt.table).action(ev); | |
if(state != status_id<type_at<transition,2>>::value) | |
state.template transit<type_at<transition,2>>(ev); | |
exec_events_<none, N+1>::exec(state, tt); | |
return; | |
} | |
} | |
exec_events_<Event, N+1>::exec(state, tt, args); | |
} | |
}; | |
template<typename Event, std::size_t N> | |
struct exec_events_<Event,N,false>{static void exec(holder&, const TransitionTable&){}template<typename T>static void exec(holder&, const TransitionTable&, T&&){}}; | |
template<typename Event> | |
void exec_events(){ | |
exec_events_<Event>::exec(state, tt); | |
} | |
template<typename Event, typename EventArgs> | |
void exec_events(const EventArgs& e){ | |
exec_events_<Event>::exec(state, tt, e); | |
} | |
public: | |
state_machine(const TransitionTable& table) : tt( table ), state(typename Statemachine::initial_state{}){} | |
state_machine(const state_machine& sm ) : tt( sm.tt ), state(typename Statemachine::initial_state{}){} | |
state_machine( state_machine&& sm ) : tt(std::move(sm.tt )), state(typename Statemachine::initial_state{}){} | |
template<typename Status> | |
bool is(const deus::impl::state<Status>&){return state == status_id<Status>::value;} | |
template<typename Event> | |
friend state_machine& operator<<=(state_machine& sm, const event<Event>& e){ | |
sm.exec_events<Event>(); | |
return sm; | |
} | |
template<typename Event, typename... Args> | |
friend state_machine& operator<<=(state_machine& sm, const event_args_wrapper<Event, Args...>& e){ | |
sm.exec_events<Event>(e); | |
return sm; | |
} | |
}; | |
template<typename StateMachine, typename Event> | |
auto forward_event(StateMachine&& sm, Event&& ev){ | |
return sm --- ev --> sm = [&sm](auto&& x){sm <<= deus::impl::event<typename std::remove_cv<typename std::remove_reference<decltype(x)>::type>::type>{};}; | |
} | |
template<typename TransitionTable, typename InitialState> | |
auto make_state_machine(const TransitionTable& tt, const InitialState&){ | |
struct sm{ | |
using transition_table = TransitionTable; | |
using initial_state = InitialState; | |
}; | |
return state_machine<sm>(tt); | |
} | |
template<typename... Transitions> | |
struct transition_table{ | |
tuple<Transitions...> table; | |
using Statuses = unique_types<type_tuple<type_at<Transitions,0>...,type_at<Transitions,2>...>>; | |
static const std::size_t size = sizeof...(Transitions); | |
}; | |
template<typename... Transitions> | |
auto make_transition_table(Transitions&&... transitions) | |
->transition_table<Transitions...>{ | |
return transition_table<Transitions...>{tuple<Transitions...>{std::forward<Transitions>(transitions)...}}; | |
} | |
} | |
using impl::state; | |
using impl::event; | |
using impl::transition; | |
using impl::state_machine; | |
using impl::forward_event; | |
using impl::make_state_machine; | |
using impl::transition_table; | |
using impl::make_transition_table; | |
} | |
namespace state{ | |
namespace detail{ | |
struct active{}; | |
struct hide{}; | |
} | |
const deus::state<detail::active> active; | |
const deus::state<detail::hide> hide; | |
} | |
namespace event{ | |
namespace detail{ | |
template<typename T> | |
struct toggle_show{ | |
T* v; | |
toggle_show(T* t)noexcept:v(t){} | |
}; | |
} | |
template<typename T>deus::event<detail::toggle_show<T>>& toggle_show(){static deus::event<detail::toggle_show<T>> e; return e;} | |
} | |
template<typename T> | |
inline auto original_skin_create_state_machine(){ | |
static auto guard = [](auto&& ev){return true;}; | |
return deus::make_state_machine( | |
deus::make_transition_table( | |
state::active ---event::toggle_show<T>()[guard]--> state::hide / [](auto&& ev){}, | |
state::hide ---event::toggle_show<T>()[guard]--> state::active / [](auto&& ev){} | |
), | |
state::active | |
); | |
} | |
template<typename T> | |
class test{ | |
using state_machine_type = decltype(original_skin_create_state_machine<test<T>>()); | |
public: | |
state_machine_type statem = original_skin_create_state_machine<test<T>>(); | |
decltype(event::toggle_show<test<T>>()(std::declval<test<T>*const>())) toggle_show; | |
test() : | |
toggle_show(event::toggle_show<test<T>>()(this)){} | |
}; | |
int main(){ | |
test<int> a; | |
a.statem <<= event::toggle_show<test<int>>()(&a); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment