Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-generator.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
76#ifndef AH_GENERATOR_H
77#define AH_GENERATOR_H
78
79#include <coroutine>
80#include <exception>
81#include <iterator>
82#include <memory>
83#include <type_traits>
84#include <utility>
85
86#include <ah-errors.H>
87
88namespace Aleph
89{
90
151template <class T>
153{
154public:
158 {
159 std::add_pointer_t<T> current_value = nullptr;
160 std::exception_ptr pending_exception = nullptr;
161
164 static std::suspend_always initial_suspend() noexcept { return {}; }
165
168 static std::suspend_always final_suspend() noexcept { return {}; }
169
172 {
173 return Generator{Handle::from_promise(*this)};
174 }
175
178 std::suspend_always yield_value(std::remove_reference_t<T> &value) noexcept
179 {
180 current_value = std::addressof(value);
181 return {};
182 }
183
185 std::suspend_always yield_value(std::remove_reference_t<T> &&value) noexcept
186 {
187 current_value = std::addressof(value);
188 return {};
189 }
190
193 static void return_void() noexcept {}
194
198 {
199 pending_exception = std::current_exception();
200 }
201
204 template <class U>
205 std::suspend_never await_transform(U &&) = delete;
206 };
207
208 using Handle = std::coroutine_handle<promise_type>;
209
218 {
220
221 public:
222 using iterator_category = std::input_iterator_tag;
223 using value_type = std::remove_reference_t<T>;
224 using difference_type = std::ptrdiff_t;
225 using reference = T &;
226 using pointer = std::add_pointer_t<T>;
227
230
233
244 {
246 << "Generator::iterator::operator++(): cannot advance past end()";
247 handle_.resume();
248 if (handle_.promise().pending_exception)
249 std::rethrow_exception(std::exchange(handle_.promise().pending_exception, nullptr));
250 return *this;
251 }
252
262 void operator++(int) { ++*this; }
263
266 {
267 return static_cast<reference>(*handle_.promise().current_value);
268 }
269
272 {
273 return handle_.promise().current_value;
274 }
275
278 {
279 return not handle_ or handle_.done();
280 }
281
283 friend bool operator==(const iterator &it, std::default_sentinel_t) noexcept
284 {
285 return it.done();
286 }
287 };
288
291
294
297 Generator(const Generator &) = delete;
298
300 Generator &operator=(const Generator &) = delete;
301
303 Generator(Generator &&o) noexcept : handle_(std::exchange(o.handle_, {})) {}
304
307 {
308 if (this != &o)
309 {
310 if (handle_)
311 handle_.destroy();
312 handle_ = std::exchange(o.handle_, {});
313 }
314 return *this;
315 }
316
320 {
321 if (handle_)
322 handle_.destroy();
323 }
324
348 {
349 if (handle_ and not handle_.done())
350 {
351 handle_.resume();
352 if (handle_.promise().pending_exception)
353 std::rethrow_exception(std::exchange(handle_.promise().pending_exception, nullptr));
354 }
355 return iterator{handle_};
356 }
357
359 static std::default_sentinel_t end() noexcept { return std::default_sentinel; }
360
361private:
363};
364
365} // end namespace Aleph
366
367#endif // AH_GENERATOR_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
long double h
Definition btreepic.C:154
size_t size_t int32_t value
Definition ca-c-api.h:116
Single-pass input iterator over the yielded sequence.
std::input_iterator_tag iterator_category
Category.
iterator() noexcept=default
Construct a singular (past-the-end-compatible) iterator.
iterator & operator++()
Resume the coroutine to its next co_yield (pre-increment).
reference operator*() const noexcept
Dereference to the most recently yielded value.
T & reference
Reference type.
bool done() const noexcept
True when the coroutine has run to completion (or was never begun).
std::add_pointer_t< T > pointer
Pointer type.
void operator++(int)
Resume the coroutine to its next co_yield (post-increment).
std::remove_reference_t< T > value_type
Element type.
std::ptrdiff_t difference_type
Distance type.
friend bool operator==(const iterator &it, std::default_sentinel_t) noexcept
Compare against the end sentinel: equal once the sequence is done.
pointer operator->() const noexcept
Member access on the most recently yielded value.
Lazy, single-pass sequence of T values produced by a coroutine.
Generator(const Generator &)=delete
Deleted: a Generator owns a single coroutine frame, which cannot be duplicated.
std::coroutine_handle< promise_type > Handle
static std::default_sentinel_t end() noexcept
End sentinel, per the C++20 sentinel-based range model.
iterator begin() &
Begin iterating: resumes the coroutine to its first co_yield.
Generator & operator=(Generator &&o) noexcept
Move assignment: destroys any owned frame, then steals o's.
Generator(Generator &&o) noexcept
Move constructor: transfers coroutine-frame ownership.
~Generator()
Destroys the coroutine frame, if any, unwinding pending local state inside the (possibly still-suspen...
Generator() noexcept=default
Construct an empty/singular Generator (no coroutine attached).
Generator & operator=(const Generator &)=delete
Deleted: see the copy constructor.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
The promise type the compiler instantiates for a coroutine returning Generator<T>.
Generator get_return_object() noexcept
Construct the Generator<T> handle returned to the caller.
void unhandled_exception() noexcept
Captures an exception thrown in the coroutine body so it can be rethrown from the resuming call (oper...
std::suspend_always yield_value(std::remove_reference_t< T > &&value) noexcept
std::suspend_never await_transform(U &&)=delete
Generators are not awaited on; co_await inside the body is intentionally unsupported to keep Generato...
std::add_pointer_t< T > current_value
static void return_void() noexcept
Generators do not return a value; co_return; (or falling off the end of the body) simply ends the seq...
static std::suspend_always initial_suspend() noexcept
A Generator starts suspended: nothing in the body runs until the first begin()/resume().
std::exception_ptr pending_exception
static std::suspend_always final_suspend() noexcept
Stay suspended at the end so the promise remains valid until the Generator is destroyed.
std::suspend_always yield_value(std::remove_reference_t< T > &value) noexcept
co_yield value; suspends the coroutine and exposes value via current_value until the next resume.