3#ifdef CXXITER_HAS_COROUTINE
6#include "../Generator.h"
7#include "../util/TraitImpl.h"
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>);
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>>;
26 TGeneratorFn generatorFn;
27 std::optional<TGenerator> currentGenerator;
29 constexpr GenerateFrom(TChainInput&& input, TGeneratorFn& generatorFn) : input(std::move(input)), generatorFn(generatorFn) {}
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;
40 using Self = op::GenerateFrom<TChainInput, TGeneratorFn, TGenerator>;
41 using Item =
typename TGenerator::value_type;
43 static constexpr inline IterValue<Item> next(Self& self) {
45 if(!self.currentGenerator.has_value()) {
46 auto item = ChainInputIterator::next(self.input);
47 if(!item.has_value()) {
return {}; }
48 self.currentGenerator.emplace(self.generatorFn( std::forward<InputItem>(item.value()) ));
51 auto item = self.currentGenerator.value().next();
52 if(!item.has_value()) {
53 self.currentGenerator.reset();
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); }