CXXIter 0.2
Loading...
Searching...
No Matches
GenerateFrom.h
1#pragma once
2
3#ifdef CXXITER_HAS_COROUTINE
4
5#include "../Common.h"
6#include "../Generator.h"
7#include "../util/TraitImpl.h"
8
9namespace CXXIter {
10
11 // ################################################################################################
12 // GENERATE FROM
13 // ################################################################################################
14
15 template<typename T, typename TItem>
16 concept GeneratorFromFunction = (util::invocable_byvalue<T, TItem> && util::is_template_instance_v<std::invoke_result_t<T, TItem>, Generator>);
17
18 namespace op {
20 template<typename TChainInput, typename TGeneratorFn, typename TGenerator>
21 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] GenerateFrom : public IterApi<GenerateFrom<TChainInput, TGeneratorFn, TGenerator>> {
22 friend struct trait::Iterator<GenerateFrom<TChainInput, TGeneratorFn, TGenerator>>;
23 friend struct trait::ExactSizeIterator<GenerateFrom<TChainInput, TGeneratorFn, TGenerator>>;
24 private:
25 TChainInput input;
26 TGeneratorFn generatorFn;
27 std::optional<TGenerator> currentGenerator;
28 public:
29 constexpr GenerateFrom(TChainInput&& input, TGeneratorFn& generatorFn) : input(std::move(input)), generatorFn(generatorFn) {}
30 };
31 }
32 // ------------------------------------------------------------------------------------------------
34 template<typename TChainInput, typename TGeneratorFn, typename TGenerator>
35 struct trait::Iterator<op::GenerateFrom<TChainInput, TGeneratorFn, TGenerator>> {
36 using ChainInputIterator = trait::Iterator<TChainInput>;
37 using InputItem = typename TChainInput::Item;
38 using InputItemOwned = typename TChainInput::ItemOwned;
39 // CXXIter Interface
40 using Self = op::GenerateFrom<TChainInput, TGeneratorFn, TGenerator>;
41 using Item = typename TGenerator::value_type;
42
43 static constexpr inline IterValue<Item> next(Self& self) {
44 while(true) {
45 if(!self.currentGenerator.has_value()) {
46 auto item = ChainInputIterator::next(self.input);
47 if(!item.has_value()) { return {}; } // reached end
48 self.currentGenerator.emplace(self.generatorFn( std::forward<InputItem>(item.value()) ));
49 }
50
51 auto item = self.currentGenerator.value().next();
52 if(!item.has_value()) {
53 self.currentGenerator.reset();
54 continue;
55 }
56 return item;
57 }
58 }
59 static constexpr inline SizeHint sizeHint(const Self& self) { return ChainInputIterator::sizeHint(self.input); }
60 static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); }
61 };
62
63}
64
65#endif
CXXIter.
Definition: CXXIter.h:48