@@ -100,7 +100,10 @@ template <typename T, enabler<T> = true> class generator {
100100 * coroutine calls `co_return`, the environment will call this function.
101101 * \param[in] v The value to set.
102102 */
103- void return_value (value_type v) { value = v; }
103+ // void return_value(value_type v) { value = v; }
104+
105+ void return_void () {}
106+
104107 /* *
105108 * \brief Sets an intermediate value from the coroutine.
106109 *
@@ -155,12 +158,12 @@ template <typename T, enabler<T> = true> class generator {
155158 * This value should only be true when the underlying generator is
156159 * finished. Iterators are compared based on this value.
157160 */
158- bool is_finished;
161+ // bool is_finished;
159162 /* *
160163 * \brief The last value from the coroutine (and thus, the value currently
161164 * held by the generator's promise).
162165 */
163- value_t value;
166+ // value_t value;
164167
165168 /* *
166169 * \brief Constructs a new iterator from a source generator.
@@ -173,8 +176,7 @@ template <typename T, enabler<T> = true> class generator {
173176 * modified).
174177 * \param[in] is_finised Is this an `end` iterator?
175178 */
176- iterator_type (gen_t &source, bool is_finised)
177- : source{source}, is_finished{is_finised} {
179+ iterator_type (gen_t &source, bool is_finised) : source{source} {
178180 if (!is_finised)
179181 ++(*this );
180182 }
@@ -190,20 +192,15 @@ template <typename T, enabler<T> = true> class generator {
190192 * \param[in] is_finised Is this iterator finished?
191193 * \param[in] value The value this iterator should hold.
192194 */
193- iterator_type (gen_t &source, bool is_finished, value_t value)
194- : source{source}, is_finished{is_finished}, value{value} {}
195+ iterator_type (gen_t &source) : source{source} {}
195196
196197 /* *
197198 * \brief Steps the generator to the next value.
198199 * \returns A new iterator for this generator, with the same state.
199200 */
200201 iter_t operator ++() {
201- if (!source)
202- is_finished = true ;
203- value = source ();
204- if (!source)
205- is_finished = true ;
206- return {source, is_finished, value};
202+ source.next ();
203+ return {source};
207204 }
208205
209206 /* *
@@ -219,19 +216,20 @@ template <typename T, enabler<T> = true> class generator {
219216 * \param[in] other The iterator to compare against.
220217 * \returns False if both are equal, otherwise true.
221218 */
222- bool operator !=(const iter_t &other) {
223- return is_finished != other.is_finished ;
224- }
219+ bool operator !=(const iter_t &) { return static_cast <bool >(source); }
225220 /* *
226221 * \brief Gets the current value from the iterator.
227222 * \returns The current value.
228223 */
229- value_t operator *() { return value; }
224+ value_t operator *() {
225+ source.contains = false ;
226+ return source._h .promise ().value ;
227+ }
230228 /* *
231229 * \brief Converts this iterator to the current value.
232230 * \returns The current value.
233231 */
234- operator value_t () { return value; }
232+ operator value_t () { return source. _h . promise (). value ; }
235233 };
236234
237235 /* *
@@ -250,12 +248,13 @@ template <typename T, enabler<T> = true> class generator {
250248 * This method should only be called from the environment.
251249 * \param[in] p The promise to use.
252250 */
253- generator (promise_type &p) : _h{handle_type::from_promise (p)} {}
251+ generator (promise_type &p)
252+ : _h{handle_type::from_promise (p)}, contains{false } {}
254253
255254 /* *
256255 * \brief Copy-constructing generators results in undefined behaviour.
257256 */
258- generator (const generator &other) = delete ;
257+ generator (const generator &other) = default ;
259258 /* *
260259 * \brief Moves the data from the other generator into this one.
261260 * \param[in,out] other The other generator.
@@ -265,7 +264,7 @@ template <typename T, enabler<T> = true> class generator {
265264 /* *
266265 * \brief Copy-assigning generators results in undefined behaviour.
267266 */
268- generator &operator =(const generator &other) = delete ;
267+ generator &operator =(const generator &other) = default ;
269268 /* *
270269 * \brief Moves the data from the other generator into this one.
271270 * \param[in,out] other The other generator.
@@ -287,7 +286,12 @@ template <typename T, enabler<T> = true> class generator {
287286 * \brief Converts this generator to a bool.
288287 * \returns True if more values remain, otherwise false.
289288 */
290- operator bool () const { return !_h.done (); }
289+ operator bool () {
290+ if (_h.done ())
291+ return false ;
292+ next ();
293+ return !_h.done ();
294+ }
291295
292296 /* *
293297 * \brief Gets an iterator to the current coroutine state.
@@ -312,15 +316,23 @@ template <typename T, enabler<T> = true> class generator {
312316 * that can be thrown from the coroutine.
313317 */
314318 value_type operator ()() {
315- if (*this )
316- _h ();
317- if (_h.promise ().ex )
318- std::rethrow_exception (_h.promise ().ex );
319- return _h.promise ().value ;
319+ next ();
320+ contains = false ;
321+ return std::move (_h.promise ().value );
320322 }
321323
322324private:
323325 handle_type _h;
326+ bool contains;
327+
328+ void next () {
329+ if (!contains) {
330+ _h ();
331+ if (_h.promise ().ex )
332+ std::rethrow_exception (_h.promise ().ex );
333+ contains = true ;
334+ }
335+ }
324336};
325337
326338} // namespace fpgen
0 commit comments