6
6
#include < coroutine>
7
7
#include < iostream>
8
8
#include < unordered_map>
9
+ #include < concepts>
10
+ #include < any>
9
11
10
12
#include " generator.h"
11
13
@@ -55,6 +57,16 @@ using coro_t = std::coroutine_handle<>;
55
57
enum class Sym : char { A, B, Term };
56
58
enum class State { A, B };
57
59
60
+ template <class State , class Sym >
61
+ class StateMachine ;
62
+
63
+ using stm_t = StateMachine<State, Sym>;
64
+
65
+ template <class F >
66
+ concept CanInvokeWithStm = requires(F f, stm_t & stm) {
67
+ { f (stm) } -> std::same_as<Resumable>;
68
+ };
69
+
58
70
Generator<Sym> input_seq (std::string seq) {
59
71
for (char c : seq) {
60
72
switch (c) {
@@ -86,9 +98,12 @@ struct stm_awaiter : public F {
86
98
auto new_state = F::operator ()(sym);
87
99
return stm[new_state];
88
100
}
89
- bool await_resume () const noexcept { return stm.genval () == Sym::Term; }
101
+ [[nodiscard]] bool await_resume () const noexcept {
102
+ return stm.genval () == Sym::Term;
103
+ }
90
104
};
91
105
106
+
92
107
template <class State , class Sym >
93
108
class StateMachine final {
94
109
public:
@@ -101,14 +116,14 @@ class StateMachine final {
101
116
return stm_awaiter (transition, *this );
102
117
}
103
118
104
- template <class F >
119
+ template <CanInvokeWithStm F>
105
120
void add_state (State state, F stf) {
106
121
states[state] = stf (*this ).handle ();
107
122
}
108
123
109
124
void run (State initial) {
110
125
current_state = initial;
111
- states[initial ].resume ();
126
+ states[current_state ].resume ();
112
127
}
113
128
114
129
Sym genval () const { return gen.current_value (); }
@@ -118,39 +133,37 @@ class StateMachine final {
118
133
State current () const { return current_state; }
119
134
120
135
private:
121
- State current_state;
122
- std::unordered_map<State, coro_t > states;
136
+ State current_state{} ;
137
+ std::unordered_map<State, coro_t > states{} ;
123
138
Generator<Sym> gen;
124
139
};
125
140
126
- using stm_t = StateMachine<State, Sym>;
127
-
128
141
Resumable StateA (stm_t & stm) {
129
- auto transmition = [](auto sym) {
142
+ auto transmission = [](auto sym) {
130
143
if (sym == Sym::B) {
131
144
return State::B;
132
145
}
133
146
return State::A;
134
147
};
135
148
for (;;) {
136
149
std::cout << " State A" << std::endl;
137
- bool finish = co_await stm.get_awaiter (transmition );
150
+ bool finish = co_await stm.get_awaiter (transmission );
138
151
if (finish) {
139
152
break ;
140
153
}
141
154
}
142
155
}
143
156
144
157
Resumable StateB (stm_t & stm) {
145
- auto transmition = [](auto sym) {
158
+ auto transmission = [](auto sym) {
146
159
if (sym == Sym::A) {
147
160
return State::A;
148
161
}
149
162
return State::B;
150
163
};
151
164
for (;;) {
152
165
std::cout << " State B" << std::endl;
153
- bool finish = co_await stm.get_awaiter (transmition );
166
+ bool finish = co_await stm.get_awaiter (transmission );
154
167
if (finish) {
155
168
break ;
156
169
}
@@ -159,7 +172,7 @@ Resumable StateB(stm_t& stm) {
159
172
160
173
int main () {
161
174
auto gen = input_seq (" aaabbaba" );
162
- stm_t stm (std::move ( gen) );
175
+ stm_t stm (gen);
163
176
stm.add_state (State::A, StateA);
164
177
stm.add_state (State::B, StateB);
165
178
0 commit comments