1 |
|
|
#pragma once |
2 |
|
|
|
3 |
|
|
#include "interfaces.hpp" |
4 |
|
|
#include <vector> |
5 |
|
|
#include <concepts> |
6 |
|
|
#include <optional> |
7 |
|
|
|
8 |
|
|
|
9 |
|
|
|
10 |
|
|
namespace next { |
11 |
|
|
|
12 |
|
|
#pragma region convert range to vector |
13 |
|
|
|
14 |
|
22 |
template <typename Range> auto to_vector_imp(Range &&range) { |
15 |
|
|
using T = std::remove_reference_t<Range>::value_type; |
16 |
|
22 |
std::vector<T> result; |
17 |
✓✗✓✗ ✓✗✓✓ ✓✗✓✗
|
182 |
for (const auto &value : range) { |
18 |
✓✗ |
80 |
result.push_back(value); |
19 |
|
|
} |
20 |
|
22 |
return result; |
21 |
|
|
} |
22 |
|
|
|
23 |
|
|
struct to_vector_proxy {}; |
24 |
|
|
|
25 |
|
10 |
auto to_vector() { return to_vector_proxy(); } |
26 |
|
|
|
27 |
|
1 |
template <typename Range> auto to_vector(Range &&range) { |
28 |
|
1 |
return to_vector_imp(std::forward<Range>(range)); |
29 |
|
|
} |
30 |
|
|
|
31 |
|
20 |
template <typename Range> auto operator|(Range &&range, to_vector_proxy) { |
32 |
|
20 |
return to_vector_imp(std::forward<Range>(range)); |
33 |
|
|
} |
34 |
|
|
|
35 |
|
|
#pragma endregion |
36 |
|
|
|
37 |
|
|
#pragma region input_range |
38 |
|
|
|
39 |
|
|
// Non-owning input view based on STL iterators |
40 |
|
|
template <typename InputIt, typename Sentinel> |
41 |
|
|
struct input_range : next_interface<input_range<InputIt, Sentinel>> { |
42 |
|
|
InputIt first; |
43 |
|
|
Sentinel last; |
44 |
|
|
InputIt current; |
45 |
|
|
|
46 |
|
1 |
input_range(InputIt first, Sentinel last) |
47 |
|
1 |
: first(first), last(last), current(first) {} |
48 |
|
|
|
49 |
|
|
using type = input_range<InputIt, Sentinel>; |
50 |
|
|
using value_type = typename std::iterator_traits<InputIt>::value_type; |
51 |
|
|
|
52 |
|
1 |
void initialize() { current = first; } |
53 |
|
|
|
54 |
|
5 |
std::optional<value_type> next() { |
55 |
✓✓ |
5 |
if (current != last) |
56 |
✓✗ |
4 |
return *current++; |
57 |
|
|
else |
58 |
|
1 |
return std::nullopt; |
59 |
|
|
} |
60 |
|
|
}; |
61 |
|
|
|
62 |
|
|
template <typename InputIt, typename Sentinel> |
63 |
|
|
input_range(InputIt, Sentinel) -> input_range<InputIt, Sentinel>; |
64 |
|
|
|
65 |
|
|
// Factory function taking anything with begin/end support and returning |
66 |
|
|
// a mutable view |
67 |
|
1 |
template <Iterable Container> auto make_range(Container &&container) { |
68 |
|
1 |
return input_range{std::begin(container), std::end(container)}; |
69 |
|
|
} |
70 |
|
|
|
71 |
|
|
template <Iterable Container, typename Proxy> |
72 |
|
1 |
auto operator|(Container &&container, Proxy &&proxy) { |
73 |
✓✗ |
1 |
return operator|(make_range(container), proxy); |
74 |
|
|
} |
75 |
|
|
|
76 |
|
|
#pragma endregion |
77 |
|
|
|
78 |
|
|
} // namespace next |