Container System 0.1.0
High-performance C++20 type-safe container framework with SIMD-accelerated serialization
Loading...
Searching...
No Matches
generator.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2024, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
28#pragma once
29
30#include <coroutine>
31#include <exception>
32#include <iterator>
33#include <utility>
34#include <type_traits>
35#include <memory>
36
38{
42 template<typename T>
43 class generator;
44
45 namespace detail
46 {
50 template<typename T>
52 {
53 using value_type = std::remove_reference_t<T>;
54 using reference_type = std::conditional_t<std::is_reference_v<T>, T, T&>;
56
58 std::exception_ptr exception_;
59
63 [[nodiscard]] generator<T> get_return_object() noexcept;
64
68 [[nodiscard]] std::suspend_always initial_suspend() noexcept
69 {
70 return {};
71 }
72
76 [[nodiscard]] std::suspend_always final_suspend() noexcept
77 {
78 return {};
79 }
80
84 std::suspend_always yield_value(value_type& value) noexcept
85 {
86 current_value_ = std::addressof(value);
87 return {};
88 }
89
93 std::suspend_always yield_value(value_type&& value) noexcept
94 {
95 current_value_ = std::addressof(value);
96 return {};
97 }
98
102 void return_void() noexcept {}
103
107 void unhandled_exception() noexcept
108 {
109 exception_ = std::current_exception();
110 }
111
115 [[nodiscard]] reference_type value() const noexcept
116 {
117 return *current_value_;
118 }
119
124 {
125 if (exception_)
126 {
127 std::rethrow_exception(exception_);
128 }
129 }
130 };
131
132 } // namespace detail
133
149 template<typename T>
151 {
152 public:
154 using handle_type = std::coroutine_handle<promise_type>;
155 using value_type = std::remove_reference_t<T>;
156 using reference = std::conditional_t<std::is_reference_v<T>, T, T&>;
158
163 {
164 public:
165 using iterator_category = std::input_iterator_tag;
166 using difference_type = std::ptrdiff_t;
170
174 iterator() noexcept : handle_(nullptr) {}
175
179 explicit iterator(handle_type handle) noexcept : handle_(handle) {}
180
184 [[nodiscard]] reference operator*() const noexcept
185 {
186 return handle_.promise().value();
187 }
188
192 [[nodiscard]] pointer operator->() const noexcept
193 {
194 return std::addressof(handle_.promise().value());
195 }
196
201 {
202 handle_.resume();
203 if (handle_.done())
204 {
205 handle_.promise().rethrow_if_exception();
206 }
207 return *this;
208 }
209
213 void operator++(int)
214 {
215 ++(*this);
216 }
217
221 [[nodiscard]] bool operator==(std::default_sentinel_t) const noexcept
222 {
223 return handle_.done();
224 }
225
229 [[nodiscard]] bool operator!=(std::default_sentinel_t) const noexcept
230 {
231 return !handle_.done();
232 }
233
234 private:
236 };
237
241 generator() noexcept : handle_(nullptr) {}
242
246 explicit generator(handle_type handle) noexcept : handle_(handle) {}
247
251 generator(generator&& other) noexcept
252 : handle_(std::exchange(other.handle_, nullptr)) {}
253
257 generator& operator=(generator&& other) noexcept
258 {
259 if (this != &other)
260 {
261 if (handle_)
262 {
263 handle_.destroy();
264 }
265 handle_ = std::exchange(other.handle_, nullptr);
266 }
267 return *this;
268 }
269
274 {
275 if (handle_)
276 {
277 handle_.destroy();
278 }
279 }
280
281 // Non-copyable
282 generator(const generator&) = delete;
283 generator& operator=(const generator&) = delete;
284
288 [[nodiscard]] bool valid() const noexcept
289 {
290 return handle_ != nullptr;
291 }
292
296 [[nodiscard]] explicit operator bool() const noexcept
297 {
298 return valid();
299 }
300
306 [[nodiscard]] iterator begin()
307 {
308 if (handle_)
309 {
310 handle_.resume();
311 if (handle_.done())
312 {
313 handle_.promise().rethrow_if_exception();
314 }
315 }
316 return iterator{handle_};
317 }
318
322 [[nodiscard]] std::default_sentinel_t end() noexcept
323 {
324 return {};
325 }
326
327 private:
329 };
330
331 // Implementation of get_return_object
332 template<typename T>
334 {
335 return generator<T>{
336 std::coroutine_handle<detail::generator_promise<T>>::from_promise(*this)};
337 }
338
346 template<typename Range>
348 {
349 for (auto&& element : range)
350 {
351 co_yield std::forward<decltype(element)>(element);
352 }
353 }
354
363 template<typename T>
364 generator<T> take(generator<T> gen, size_t count)
365 {
366 size_t yielded = 0;
367 for (auto&& element : gen)
368 {
369 if (yielded++ >= count)
370 {
371 break;
372 }
373 co_yield std::forward<decltype(element)>(element);
374 }
375 }
376
377} // namespace kcenon::container::async
iterator & operator++()
Pre-increment operator.
Definition generator.h:200
iterator() noexcept
Default constructor - creates end iterator.
Definition generator.h:174
bool operator==(std::default_sentinel_t) const noexcept
Equality comparison.
Definition generator.h:221
void operator++(int)
Post-increment operator.
Definition generator.h:213
bool operator!=(std::default_sentinel_t) const noexcept
Inequality comparison.
Definition generator.h:229
iterator(handle_type handle) noexcept
Construct from coroutine handle.
Definition generator.h:179
reference operator*() const noexcept
Dereference operator.
Definition generator.h:184
pointer operator->() const noexcept
Arrow operator.
Definition generator.h:192
Forward declaration of generator.
Definition generator.h:151
iterator begin()
Get iterator to beginning.
Definition generator.h:306
generator(generator &&other) noexcept
Move constructor.
Definition generator.h:251
generator(const generator &)=delete
generator() noexcept
Default constructor - creates empty generator.
Definition generator.h:241
bool valid() const noexcept
Check if generator is valid.
Definition generator.h:288
std::default_sentinel_t end() noexcept
Get sentinel for end.
Definition generator.h:322
generator & operator=(const generator &)=delete
std::remove_reference_t< T > value_type
Definition generator.h:155
std::coroutine_handle< promise_type > handle_type
Definition generator.h:154
generator(handle_type handle) noexcept
Construct from coroutine handle.
Definition generator.h:246
generator & operator=(generator &&other) noexcept
Move assignment operator.
Definition generator.h:257
~generator()
Destructor - destroys the coroutine if owned.
Definition generator.h:273
std::conditional_t< std::is_reference_v< T >, T, T & > reference
Definition generator.h:156
Enhanced type-safe value with perfect legacy compatibility.
Definition value.h:129
generator< T > take(generator< T > gen, size_t count)
Create a generator that yields a fixed number of elements.
Definition generator.h:364
generator< typename std::ranges::range_value_t< Range > > from_range(Range &&range)
Create a generator from a range.
Definition generator.h:347
std::suspend_always final_suspend() noexcept
Suspend at final point.
Definition generator.h:76
std::suspend_always yield_value(value_type &value) noexcept
Yield a value.
Definition generator.h:84
std::suspend_always initial_suspend() noexcept
Suspend at start - generators are lazy.
Definition generator.h:68
generator< T > get_return_object() noexcept
Get return object (the generator)
Definition generator.h:333
void unhandled_exception() noexcept
Handle unhandled exceptions.
Definition generator.h:107
std::conditional_t< std::is_reference_v< T >, T, T & > reference_type
Definition generator.h:54
std::suspend_always yield_value(value_type &&value) noexcept
Yield an rvalue.
Definition generator.h:93
void return_void() noexcept
Generators don't return values directly.
Definition generator.h:102
reference_type value() const noexcept
Get the current value.
Definition generator.h:115
void rethrow_if_exception()
Rethrow stored exception if any.
Definition generator.h:123