-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathredux.hpp
127 lines (98 loc) · 3.21 KB
/
redux.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#pragma once
#include <vector>
#include <functional>
//=============================================================================
namespace redux
{
//=============================================================================
template<
typename StateType,
typename ActionType,
typename ReducerType>
class store_t
{
public:
using state_t = StateType;
using action_t = ActionType;
using reducer_t = ReducerType;
using next_t = std::function<void(action_t)>;
using middleware_t = std::function<void(store_t& store, next_t next, action_t action)>;
using subscriber_t = std::function<void(state_t)>;
store_t(const store_t& other) = delete;
store_t(ReducerType reducer, state_t state)
: state(state)
, next(innermost_next(reducer))
{
}
void dispatch(action_t action)
{
next(action);
}
const state_t& get_state() const
{
return state;
}
void subscribe(subscriber_t subscriber)
{
subscribers.push_back(subscriber);
}
store_t& apply_middleware(middleware_t middleware)
{
next = [this, old_next=next, middleware] (auto action)
{
middleware(*this, old_next, action);
};
return *this;
}
private:
//=========================================================================
next_t innermost_next(reducer_t reducer)
{
return [this, reducer] (auto action)
{
state = reducer(state, action);
for (auto subscriber : subscribers)
{
subscriber(state);
}
};
}
next_t next;
state_t state;
std::vector<subscriber_t> subscribers;
};
//=============================================================================
namespace detail
{
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
typedef ReturnType result_type;
enum { arity = sizeof...(Args) };
template <size_t i> struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
};
}
//=============================================================================
template<
typename ReducerType,
typename StateType = typename detail::function_traits<ReducerType>::template arg<0>::type,
typename ActionType = typename detail::function_traits<ReducerType>::template arg<1>::type>
auto create_store(ReducerType reducer, StateType state=StateType())
{
return store_t<StateType, ActionType, ReducerType>(reducer, state);
}
//=============================================================================
template<
typename ReducerType,
typename StateType = typename detail::function_traits<ReducerType>::template arg<0>::type,
typename ActionType = typename detail::function_traits<ReducerType>::template arg<1>::type>
auto create_store_ptr(ReducerType reducer, StateType state=StateType())
{
return std::make_unique<store_t<StateType, ActionType, ReducerType>>(reducer, state);
}
} // namespace redux