forked from ryanhaining/cppitertools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sorted.hpp
173 lines (143 loc) · 4.94 KB
/
sorted.hpp
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#ifndef ITER_SORTED_HPP_
#define ITER_SORTED_HPP_
#include "internal/iteratoriterator.hpp"
#include "internal/iterbase.hpp"
#include <algorithm>
#include <functional>
#include <iterator>
#include <vector>
namespace iter {
namespace impl {
template <typename Container, typename CompareFunc>
class SortedView;
using SortedFn = IterToolFnOptionalBindSecond<SortedView, std::less<>>;
}
constexpr impl::SortedFn sorted{};
}
template <typename Container, typename CompareFunc>
class iter::impl::SortedView {
private:
template <typename ContainerT, typename = void>
class SortedItersHolder {
public:
using IterIterWrap =
IterIterWrapper<std::vector<iterator_type<ContainerT>>>;
using ItIt = iterator_type<IterIterWrap>;
using ConstItIt = void;
private:
ContainerT container_;
IterIterWrap sorted_iters_;
public:
SortedItersHolder(ContainerT&& container, CompareFunc compare_func)
: container_(std::forward<ContainerT>(container)) {
// Fill the sorted_iters_ vector with an iterator to each
// element in the container_
for (auto iter = get_begin(container_); iter != get_end(container_);
++iter) {
sorted_iters_.get().push_back(iter);
}
// sort by comparing the elements that the iterators point to
std::sort(get_begin(sorted_iters_.get()), get_end(sorted_iters_.get()),
[compare_func](
iterator_type<Container> it1, iterator_type<Container> it2) {
return std::invoke(compare_func, *it1, *it2);
});
}
ItIt begin() {
return sorted_iters_.begin();
}
ItIt end() {
return sorted_iters_.end();
}
};
template <typename ContainerT>
class SortedItersHolder<ContainerT,
std::void_t<decltype(std::begin(std::declval<AsConst<ContainerT>&>()))>> {
public:
using IterIterWrap =
IterIterWrapper<std::vector<iterator_type<ContainerT>>>;
using ItIt = iterator_type<IterIterWrap>;
using ConstIterIterWrap =
IterIterWrapper<std::vector<iterator_type<AsConst<ContainerT>>>>;
using ConstItIt = iterator_type<ConstIterIterWrap>;
private:
ContainerT container_;
mutable CompareFunc compare_func_;
IterIterWrap sorted_iters_;
mutable ConstIterIterWrap const_sorted_iters_;
void populate_sorted_iters() const = delete;
void populate_sorted_iters() {
if (!sorted_iters_.empty()) {
return;
}
// Fill the sorted_iters_ vector with an iterator to each
// element in the container_
for (auto iter = get_begin(container_); iter != get_end(container_);
++iter) {
sorted_iters_.get().push_back(iter);
}
// sort by comparing the elements that the iterators point to
std::sort(get_begin(sorted_iters_.get()), get_end(sorted_iters_.get()),
[this](iterator_type<ContainerT> it1, iterator_type<ContainerT> it2) {
return std::invoke(compare_func_, *it1, *it2);
});
}
void populate_const_sorted_iters() = delete;
void populate_const_sorted_iters() const {
if (!const_sorted_iters_.empty()) {
return;
}
for (auto iter = get_begin(std::as_const(container_));
iter != get_end(std::as_const(container_)); ++iter) {
const_sorted_iters_.get().push_back(iter);
}
// sort by comparing the elements that the iterators point to
std::sort(get_begin(const_sorted_iters_.get()),
get_end(const_sorted_iters_.get()),
[this](iterator_type<AsConst<ContainerT>> it1,
iterator_type<AsConst<ContainerT>> it2) {
return compare_func_(*it1, *it2);
});
}
public:
SortedItersHolder(ContainerT&& container, CompareFunc compare_func)
: container_(std::forward<ContainerT>(container)),
compare_func_(std::move(compare_func)) {}
ItIt begin() {
populate_sorted_iters();
return sorted_iters_.begin();
}
ItIt end() {
populate_sorted_iters();
return sorted_iters_.end();
}
ConstItIt begin() const {
populate_const_sorted_iters();
return const_sorted_iters_.begin();
}
ConstItIt end() const {
populate_const_sorted_iters();
return const_sorted_iters_.end();
}
};
friend SortedFn;
SortedItersHolder<Container> sorted_iters_holder_;
SortedView(Container&& container, CompareFunc compare_func)
: sorted_iters_holder_{
std::forward<Container>(container), std::move(compare_func)} {}
public:
SortedView(SortedView&&) = default;
typename SortedItersHolder<Container>::ItIt begin() {
return sorted_iters_holder_.begin();
}
typename SortedItersHolder<Container>::ItIt end() {
return sorted_iters_holder_.end();
}
typename SortedItersHolder<Container>::ConstItIt begin() const {
return sorted_iters_holder_.begin();
}
typename SortedItersHolder<Container>::ConstItIt end() const {
return sorted_iters_holder_.end();
}
};
#endif