4#include "../util/TraitImpl.h"
13 template<
typename TChainInput,
typename TFilterMapFn,
typename TItem>
14 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] FilterMap :
public IterApi<FilterMap<TChainInput, TFilterMapFn, TItem>> {
15 friend struct trait::Iterator<FilterMap<TChainInput, TFilterMapFn, TItem>>;
16 friend struct trait::DoubleEndedIterator<FilterMap<TChainInput, TFilterMapFn, TItem>>;
19 TFilterMapFn filterMapFn;
21 constexpr FilterMap(TChainInput&& input, TFilterMapFn filterMapFn) : input(std::move(input)), filterMapFn(filterMapFn) {}
26 template<
typename TChainInput,
typename TFilterMapFn,
typename TItem>
27 struct trait::Iterator<op::FilterMap<TChainInput, TFilterMapFn, TItem>> {
28 using ChainInputIterator = trait::Iterator<TChainInput>;
29 using InputItem =
typename TChainInput::Item;
31 using Self = op::FilterMap<TChainInput, TFilterMapFn, TItem>;
34 static constexpr inline IterValue<Item> next(Self& self) {
36 auto item = ChainInputIterator::next(self.input);
37 if(!item.has_value()) [[unlikely]] {
return {}; }
38 std::optional<Item> value(self.filterMapFn(std::forward<InputItem>( item.value() )));
39 if(!value) {
continue; }
43 static constexpr inline SizeHint sizeHint(
const Self& self) {
44 SizeHint input = ChainInputIterator::sizeHint(self.input);
45 return SizeHint(0, input.upperBound);
47 static constexpr inline size_t advanceBy(Self& self,
size_t n) {
return util::advanceByPull(self, n); }
50 template<CXXIterDoubleEndedIterator TChainInput,
typename TFilterMapFn,
typename TItem>
51 struct trait::DoubleEndedIterator<op::FilterMap<TChainInput, TFilterMapFn, TItem>> {
52 using ChainInputIterator = trait::DoubleEndedIterator<TChainInput>;
53 using InputItem =
typename TChainInput::Item;
55 using Self = op::FilterMap<TChainInput, TFilterMapFn, TItem>;
58 static constexpr inline IterValue<Item> nextBack(Self& self) {
60 auto item = ChainInputIterator::nextBack(self.input);
61 if(!item.has_value()) [[unlikely]] {
return {}; }
62 std::optional<Item> value(self.filterMapFn(std::forward<InputItem>( item.value() )));
63 if(!value) {
continue; }