Skip to content

Instantly share code, notes, and snippets.

@wx257osn2
Last active August 29, 2015 14:16
Show Gist options
  • Save wx257osn2/8cee1725d5275e9993ce to your computer and use it in GitHub Desktop.
Save wx257osn2/8cee1725d5275e9993ce to your computer and use it in GitHub Desktop.
ICE at Torino(VC++ Nov 2013 CTP)
#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