CXXIter 0.2
Loading...
Searching...
No Matches
FlatMap.h
1#pragma once
2
3#include <utility>
4#include <optional>
5
6#include "../Common.h"
7#include "../sources/ContainerSources.h"
8#include "../util/TraitImpl.h"
9
10namespace CXXIter {
11
12 // ################################################################################################
13 // FLATMAP
14 // ################################################################################################
15 namespace op {
17 template<typename TChainInput, typename TFlatMapFn, typename TItemContainer>
18 requires (!std::is_reference_v<TItemContainer>)
19 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] FlatMap : public IterApi<FlatMap<TChainInput, TFlatMapFn, TItemContainer>> {
20 friend struct trait::Iterator<FlatMap<TChainInput, TFlatMapFn, TItemContainer>>;
21 private:
22 TChainInput input;
23 std::optional<SrcMov<TItemContainer>> current;
24 TFlatMapFn mapFn;
25 public:
26 constexpr FlatMap(TChainInput&& input, TFlatMapFn mapFn) : input(std::move(input)), mapFn(mapFn) {}
27 };
28 }
29 // ------------------------------------------------------------------------------------------------
31 template<typename TChainInput, typename TFlatMapFn, typename TItemContainer>
32 struct trait::Iterator<op::FlatMap<TChainInput, TFlatMapFn, TItemContainer>> {
33 using NestedChainIterator = trait::Iterator<SrcMov<TItemContainer>>;
34 using ChainInputIterator = trait::Iterator<TChainInput>;
35 using InputItem = typename ChainInputIterator::Item;
36 // CXXIter Interface
37 using Self = op::FlatMap<TChainInput, TFlatMapFn, TItemContainer>;
38 using Item = typename TItemContainer::value_type;
39
40 static constexpr inline IterValue<Item> next(Self& self) {
41 while(true) {
42 if(!self.current) { // pull new container from the outer iterator
43 auto item = ChainInputIterator::next(self.input);
44 if(!item.has_value()) [[unlikely]] { return {}; } // end of iteration
45 self.current = SrcMov(std::move(
46 self.mapFn(std::forward<InputItem>( item.value() ))
47 ));
48 }
49
50 // if the outer iterator yielded a container, take from it until we reach the end
51 auto item = NestedChainIterator::next(*self.current);
52 if(item.has_value()) [[likely]] { // inner yielded a usable item
53 return item.value();
54 } else [[unlikely]] {
55 self.current.reset(); // inner container ended, unset current cache
56 }
57 }
58 }
59 static constexpr inline SizeHint sizeHint(const Self&) { return SizeHint(); }
60 static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); }
61 };
62
63}
CXXIter.
Definition: CXXIter.h:48
static constexpr IterValue< Item > next(Self &self)=delete
Pull one element from the iterator pipeline previous to this pipeline-element.
void Item
Item-Type. This is the type of elements that can be pulled from this pipeline-element.
Definition: Traits.h:32
trait::Iterator< T > Self
Self-Type. This is the type of the struct for which the trait::Iterator is being specialized.
Definition: Traits.h:28
static constexpr SizeHint sizeHint(const Self &self)=delete
Get the bounds on the remaining length of the iterator pipeline until this pipeline-element,...
static constexpr size_t advanceBy(Self &self, size_t n)=delete
Advance the iterator by n elements.