1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#pragma once
#include <util/generic/iterator_range.h>
#include <util/generic/store_policy.h>
#include <iterator>
template <class TIterator, class TCondition>
class TFilteringIterator {
public:
using TSelf = TFilteringIterator<TIterator, TCondition>;
using difference_type = typename std::iterator_traits<TIterator>::difference_type;
using value_type = typename std::iterator_traits<TIterator>::value_type;
using reference = typename std::iterator_traits<TIterator>::reference;
using pointer = typename std::iterator_traits<TIterator>::pointer;
using iterator_category = std::forward_iterator_tag;
TFilteringIterator(TIterator it, TIterator last, const TCondition& condition)
: Iter(it)
, Last(last)
, Condition(condition)
{
Grep();
}
TSelf& operator++() {
++Iter;
Grep();
return *this;
}
decltype(auto) operator*() const {
return *Iter;
}
pointer operator->() const {
return &*Iter;
}
bool operator==(const TSelf& other) const {
return Iter == other.Iter;
}
bool operator!=(const TSelf& other) const {
return Iter != other.Iter;
}
private:
void Grep() {
while (Iter != Last && !Condition(*Iter)) {
++Iter;
}
}
TIterator Iter;
TIterator Last;
TCondition Condition;
};
template <class TContainer, class TCondition>
class TFilteringRange {
using TContainerStorage = TAutoEmbedOrPtrPolicy<TContainer>;
using TConditionStorage = TAutoEmbedOrPtrPolicy<TCondition>;
using TRawIterator = decltype(std::begin(std::declval<TContainer&>()));
using TConditionWrapper = std::reference_wrapper<std::remove_reference_t<TCondition>>;
public:
//TODO: make TIterator typedef private
using TIterator = TFilteringIterator<TRawIterator, TConditionWrapper>;
using iterator = TIterator;
using const_iterator = TIterator;
using value_type = typename TIterator::value_type;
using reference = typename TIterator::reference;
TFilteringRange(TContainer&& container, TCondition&& predicate)
: Container(std::forward<TContainer>(container))
, Condition(std::forward<TCondition>(predicate))
{}
TIterator begin() const {
return {std::begin(*Container.Ptr()), std::end(*Container.Ptr()), {*Condition.Ptr()}};
}
TIterator end() const {
return {std::end(*Container.Ptr()), std::end(*Container.Ptr()), {*Condition.Ptr()}};
}
private:
mutable TContainerStorage Container;
mutable TConditionStorage Condition;
};
template <class TIterator, class TCondition>
auto MakeFilteringRange(TIterator begin, TIterator end, const TCondition& condition) {
return MakeIteratorRange(TFilteringIterator<TIterator, TCondition>(begin, end, condition), TFilteringIterator<TIterator, TCondition>(end, end, condition));
}
template <class TContainer, class TCondition>
auto MakeFilteringRange(TContainer&& container, TCondition&& condition) {
return TFilteringRange<TContainer, TCondition>(std::forward<TContainer>(container), std::forward<TCondition>(condition));
}
|