CkPttn 1.2.4
Loading...
Searching...
No Matches
transrangers.hpp
Go to the documentation of this file.
1
15#ifndef JOAQUINTIDES_TRANSRANGERS_HPP
16#define JOAQUINTIDES_TRANSRANGERS_HPP
17
18#if defined(_MSC_VER)
19# pragma once
20#endif
21
22#include <iterator>
23// #include <optional>
24#include <tuple>
25#include <type_traits>
26#include <utility>
27
28#if defined(__clang__)
29# define TRANSRANGERS_HOT __attribute__((flatten))
30# define TRANSRANGERS_HOT_MUTABLE __attribute__((flatten)) mutable
31#elif defined(__GNUC__)
32# define TRANSRANGERS_HOT __attribute__((flatten))
33# define TRANSRANGERS_HOT_MUTABLE mutable __attribute__((flatten))
34#else
35# define TRANSRANGERS_HOT [[msvc::forceinline]]
36# define TRANSRANGERS_HOT_MUTABLE mutable [[msvc::forceinline]]
37#endif
38
39namespace transrangers {
40
41 template <typename Cursor, typename F> struct ranger_class : F {
42 using cursor = Cursor;
43 };
44
45 template <typename Cursor, typename F> auto ranger(F f) { return ranger_class<Cursor, F>{f}; }
46
47 // all, all_copy
48 template <typename Range> auto all(Range&& rng) {
49 using std::begin;
50 using std::end;
51 using cursor = decltype(begin(rng));
52
53 return ranger<cursor>([first = begin(rng), last = end(rng)](auto dst)
55 auto it = first;
56 while (it != last) {
57 if (!dst(it++)) {
58 first = it;
59 return false;
60 }
61 }
62 return true;
63 });
64 }
65
66 template <typename Range> struct all_copy {
67 using ranger = decltype(all(std::declval<Range&>()));
68 using cursor = typename ranger::cursor;
69
70 template <typename F> auto operator()(const F& p) { return rgr(p); }
71
72 Range rng;
74 };
75
76 template <typename Range>
77 typename std::enable_if<std::is_rvalue_reference<Range&&>::value, all_copy<Range>>::type all(
78 Range&& rng) {
79 return all_copy<Range>{std::move(rng)};
80 }
81
82 // filter
83 template <typename Pred> auto pred_box(Pred pred) {
84 return [=](auto&&... x) -> int { return pred(std::forward<decltype(x)>(x)...); };
85 }
86
87 template <typename Pred, typename Ranger> auto filter(Pred pred_, Ranger rgr) {
88 using cursor = typename Ranger::cursor;
89
90 return ranger<cursor>([=, pred = pred_box(pred_)](auto dst) TRANSRANGERS_HOT_MUTABLE {
91 return rgr([&](const auto& p) TRANSRANGERS_HOT { return pred(*p) ? dst(p) : true; });
92 });
93 }
94
95 template <typename Cursor, typename F, typename = void> struct deref_fun {
96 decltype(auto) operator*() const { return (*pf)(*p); }
97
98 Cursor p;
99 F* pf;
100 };
101
102 template <typename Cursor, typename F>
103 struct deref_fun<Cursor, F,
104 typename std::enable_if<std::is_trivially_default_constructible<F>::value
105 && std::is_empty<F>::value>::type> {
106 deref_fun(Cursor p = {}, F* = nullptr) : p{p} {}
107
108 decltype(auto) operator*() const { return F()(*p); }
109
110 Cursor p;
111 };
112
113 // transform
114 template <typename F, typename Ranger> auto transform(F f, Ranger rgr) {
116
117 return ranger<cursor>([=](auto dst) TRANSRANGERS_HOT_MUTABLE {
118 return rgr([&](const auto& p) TRANSRANGERS_HOT { return dst(cursor{p, &f}); });
119 });
120 }
121
122 // take
123 template <typename Ranger> auto take(int n, Ranger rgr) {
124 using cursor = typename Ranger::cursor;
125
126 return ranger<cursor>([=](auto dst) TRANSRANGERS_HOT_MUTABLE {
127 if (n)
128 return rgr([&](const auto& p) TRANSRANGERS_HOT {
129 --n;
130 return dst(p) && (n != 0);
131 })
132 || (n == 0);
133 else
134 return true;
135 });
136 }
137
138 // concat
139 template <typename Ranger> auto concat(Ranger rgr) { return rgr; }
140
141 template <typename Ranger, typename... Rangers> auto concat(Ranger rgr, Rangers... rgrs) {
142 using cursor = typename Ranger::cursor;
143
144 return ranger<cursor>([=, cont = false, next = concat(rgrs...)](auto dst)
146 if (!cont) {
147 if (!(cont = rgr(dst))) return false;
148 }
149 return next(dst);
150 });
151 }
152
153 // unique
154 template <typename Ranger> auto unique(Ranger rgr) {
155 using cursor = typename Ranger::cursor;
156
157 return ranger<cursor>([=, start = true, p = cursor{}](auto dst) TRANSRANGERS_HOT_MUTABLE {
158 if (start) {
159 start = false;
160 if (rgr([&](const auto& q) TRANSRANGERS_HOT {
161 p = q;
162 return false;
163 }))
164 return true;
165 if (!dst(p)) return false;
166 }
167 return rgr([&, prev = p](const auto& q) TRANSRANGERS_HOT_MUTABLE {
168 if ((*prev == *q) || dst(q)) {
169 prev = q;
170 return true;
171 } else {
172 p = q;
173 return false;
174 }
175 });
176 });
177 }
178
179 // join
181 template <typename T> static decltype(auto) adapt(T&& srgr) {
182 return std::forward<decltype(srgr)>(srgr);
183 }
184 };
185
186 // template <typename Ranger, typename Adaption = identity_adaption>
187 // auto join(Ranger rgr) {
188 // using cursor = typename Ranger::cursor;
189 // using subranger =
190 // std::remove_cv_t<std::remove_reference_t<decltype(Adaption::adapt(
191 // *std::declval<const cursor &>()))>>;
192 // using subranger_cursor = typename subranger::cursor;
193
194 // return ranger<subranger_cursor>([=, osrgr = std::optional<subranger>{}](
195 // auto dst) TRANSRANGERS_HOT_MUTABLE {
196 // if (osrgr) {
197 // if (!(*osrgr)(dst))
198 // return false;
199 // }
200 // return rgr([&](const auto &p) TRANSRANGERS_HOT {
201 // auto srgr = Adaption::adapt(*p);
202 // if (!srgr(dst)) {
203 // osrgr.emplace(std::move(srgr));
204 // return false;
205 // } else
206 // return true;
207 // });
208 // });
209 // }
210
212 template <typename T> static auto adapt(T&& srgn) {
213 return all(std::forward<decltype(srgn)>(srgn));
214 }
215 };
216
217 // template <typename Ranger> auto ranger_join(Ranger rgr) {
218 // return join<Ranger, all_adaption>(std::move(rgr));
219 // }
220
221 // zip
222 template <typename... Rangers> struct zip_cursor {
223 auto operator*() const {
224 return std::apply(
225 [](const auto&... ps) { return std::tuple<decltype(*ps)...>{*ps...}; }, ps);
226 }
227
228 std::tuple<typename Rangers::cursor...> ps;
229 };
230
231 // template <typename Ranger, typename... Rangers>
232 // auto zip(Ranger rgr, Rangers... rgrs) {
233 // using cursor = zip_cursor<Ranger, Rangers...>;
234 //
235 // return ranger<cursor>([=, zp = cursor{}](auto dst) TRANSRANGERS_HOT_MUTABLE
236 // {
237 // bool finished = false;
238 // return rgr([&finished, &zp, &dst,
239 // &rgrs...](const auto &p) TRANSRANGERS_HOT {
240 // std::get<0>(zp.ps) = p;
241 // if ([&zp, &rgrs... ]<std::size_t... I>(std::index_sequence<I...>
242 // #ifdef _MSC_VER
243 // ,
244 // auto &...rgrs
245 // #endif
246 // ) TRANSRANGERS_HOT {
247 // return (rgrs([&zp](const auto &p) TRANSRANGERS_HOT {
248 // std::get<I + 1>(zp.ps) = p;
249 // return false;
250 // }) ||
251 // ...);
252 // }(std::index_sequence_for<Rangers...>{}
253 // #ifdef _MSC_VER
254 // ,
255 // rgrs...
256 // #endif
257 // )) {
258 // finished = true;
259 // return false;
260 // }
261 //
262 // return dst(zp);
263 // }) ||
264 // finished;
265 // });
266 // }
267
268 // template <typename Ranger1, typename Ranger2> struct zip2_cursor {
269 // auto operator*() const {
270 // return std::apply(
271 // [](const auto &p1, const auto &p2) {
272 // return std::tuple<decltype(p1), decltype(p2)>{*p1, *p2};
273 // },
274 // ps);
275 // }
276 //
277 // std::tuple<typename Ranger1::cursor, typename Ranger2::cursor> ps;
278 // };
279
280 template <typename Ranger1, typename Ranger2> auto zip2(Ranger1 rgr1, Ranger2 rgr2) {
281 using cursor = zip_cursor<Ranger1, Ranger2>;
282
283 return ranger<cursor>([=, zp = cursor{}](auto dst) TRANSRANGERS_HOT_MUTABLE {
284 bool finished = false;
285 return rgr1([&](const auto& p) TRANSRANGERS_HOT {
286 std::get<0>(zp.ps) = p;
287 if (rgr2([&](const auto& p) TRANSRANGERS_HOT {
288 std::get<1>(zp.ps) = p;
289 return false;
290 })) {
291 finished = true;
292 return false;
293 }
294 return dst(zp);
295 })
296 || finished;
297 });
298 }
299
300 // accumulate
301 template <typename Ranger, typename T> T accumulate(Ranger rgr, T init) {
302 rgr([&](const auto& p) TRANSRANGERS_HOT {
303 init = std::move(init) + *p;
304 return true;
305 });
306 return init;
307 }
308
309} // namespace transrangers
310
311#undef TRANSRANGERS_HOT_MUTABLE
312#undef TRANSRANGERS_HOT
313#endif
Definition transranger_view.hpp:25
auto concat(Ranger rgr)
Definition transrangers.hpp:139
auto pred_box(Pred pred)
Definition transrangers.hpp:83
auto zip2(Ranger1 rgr1, Ranger2 rgr2)
Definition transrangers.hpp:280
auto unique(Ranger rgr)
Definition transrangers.hpp:154
T accumulate(Ranger rgr, T init)
Definition transrangers.hpp:301
auto filter(Pred pred_, Ranger rgr)
Definition transrangers.hpp:87
auto all(Range &&rng)
Definition transrangers.hpp:48
auto ranger(F f)
Definition transrangers.hpp:45
auto transform(F f, Ranger rgr)
Definition transrangers.hpp:114
auto take(int n, Ranger rgr)
Definition transrangers.hpp:123
Definition transrangers.hpp:211
static auto adapt(T &&srgn)
Definition transrangers.hpp:212
Definition transrangers.hpp:66
typename ranger::cursor cursor
Definition transrangers.hpp:68
Range rng
Definition transrangers.hpp:72
auto operator()(const F &p)
Definition transrangers.hpp:70
ranger rgr
Definition transrangers.hpp:73
decltype(all(std::declval< Range & >())) ranger
Definition transrangers.hpp:67
Definition transrangers.hpp:95
F * pf
Definition transrangers.hpp:99
Cursor p
Definition transrangers.hpp:98
Definition transrangers.hpp:180
static decltype(auto) adapt(T &&srgr)
Definition transrangers.hpp:181
Definition transrangers.hpp:41
Cursor cursor
Definition transrangers.hpp:42
Definition transrangers.hpp:222
std::tuple< typename Rangers::cursor... > ps
Definition transrangers.hpp:228
auto operator*() const
Definition transrangers.hpp:223
#define TRANSRANGERS_HOT
Definition transrangers.hpp:35
#define TRANSRANGERS_HOT_MUTABLE
Definition transrangers.hpp:36