@@ -9,203 +9,23 @@ module;
9
9
10
10
export module containers.algorithms.join;
11
11
12
- import containers.begin_end;
13
- export import containers.common_iterator_functions;
14
- import containers.is_empty;
15
- import containers.iter_difference_t ;
16
- import containers.iter_reference_t ;
17
- import containers.iter_value_t ;
18
- import containers.iterator_t ;
12
+ import containers.algorithms.join_with;
13
+ import containers.array;
19
14
import containers.range;
20
- import containers.range_reference_t ;
21
- import containers.range_size_t ;
22
- import containers.sentinel_t ;
15
+ import containers.range_value_t ;
23
16
24
17
import bounded;
25
- import std_module;
26
- import tv;
27
18
28
19
namespace containers {
29
20
using namespace bounded ::literal;
30
21
31
- template <typename Range>
32
- struct inner_range {
33
- inner_range () = default ;
34
- inner_range (inner_range &&) = default ;
35
- inner_range (inner_range const &) = delete ;
36
- auto operator =(inner_range &&) & -> inner_range & = default ;
37
- auto operator =(inner_range const &) & -> inner_range & = delete ;
38
-
39
- constexpr auto set (auto const & outer_it) & -> void {
40
- m_range.emplace ([&] { return *outer_it; });
41
- m_it = containers::begin (std::move (*m_range));
42
- }
43
-
44
- constexpr auto begin () const -> decltype(auto ) {
45
- return m_it;
46
- }
47
- // Requires that `set` has already been called
48
- constexpr auto end () const -> decltype(auto ) {
49
- return containers::end (*m_range);
50
- }
51
-
52
- constexpr auto advance () & -> void {
53
- ++m_it;
54
- }
55
-
56
- private:
57
- tv::optional<Range> m_range{};
58
- iterator_t <Range> m_it{};
59
- };
60
-
61
- template <typename Range>
62
- struct inner_range_iterator {
63
- constexpr inner_range_iterator (inner_range<Range> & range):
64
- m_range(range)
65
- {
66
- }
67
- constexpr auto set (auto const & outer_it) const -> void {
68
- m_range.get ().set (outer_it);
69
- }
70
-
71
- constexpr auto begin () const -> decltype(auto ) {
72
- return m_range.get ().begin ();
73
- }
74
- // Requires that `set` has already been called
75
- constexpr auto end () const -> decltype(auto ) {
76
- return m_range.get ().end ();
77
- }
78
-
79
- constexpr auto advance () const -> void {
80
- m_range.get ().advance ();
81
- }
82
-
83
- private:
84
- std::reference_wrapper<inner_range<Range>> m_range;
85
- };
86
-
87
- template <typename Range> requires std::is_reference_v<Range>
88
- struct inner_range <Range> {
89
- };
90
-
91
- template <typename Range> requires std::is_reference_v<Range>
92
- struct inner_range_iterator <Range> {
93
- constexpr inner_range_iterator (inner_range<Range>):
94
- m_it(),
95
- m_last()
96
- {
97
- }
98
- constexpr auto set (auto const & outer_it) & -> void {
99
- auto && range = *outer_it;
100
- m_it = containers::begin (range);
101
- m_last = containers::end (range);
102
- }
103
-
104
- constexpr auto begin () const -> iterator_t<Range> const & {
105
- return m_it;
106
- }
107
- constexpr auto end () const -> sentinel_t<Range> const & {
108
- return m_last;
109
- }
110
-
111
- constexpr auto advance () & -> void {
112
- ++m_it;
113
- }
114
-
115
- private:
116
- iterator_t <Range> m_it;
117
- sentinel_t <Range> m_last;
118
- };
119
-
120
- // TODO: It's possible to more efficiently add and subtract iterators
121
- template <typename Iterator, typename Sentinel>
122
- struct join_iterator {
123
- using difference_type = decltype (
124
- bounded::declval<iter_difference_t <Iterator>>() *
125
- bounded::declval<range_size_t <iter_value_t <Iterator>>>()
126
- );
127
- explicit constexpr join_iterator (
128
- Iterator it,
129
- Sentinel last,
130
- inner_range<iter_reference_t <Iterator>> & inner
131
- ):
132
- m_outer_it(std::move(it)),
133
- m_outer_last(std::move(last)),
134
- m_inner(inner)
135
- {
136
- if (m_outer_it != m_outer_last) {
137
- m_inner.set (m_outer_it);
138
- normalize ();
139
- }
140
- }
141
-
142
- constexpr auto operator *() const -> decltype (auto ) {
143
- return *m_inner.begin ();
144
- }
145
- friend constexpr auto operator +(join_iterator lhs, bounded::constant_t <1 >) {
146
- lhs.m_inner .advance ();
147
- lhs.normalize ();
148
- return lhs;
149
- }
150
- friend constexpr auto operator ==(join_iterator const & lhs, join_iterator const & rhs) -> bool {
151
- return
152
- lhs.m_outer_it == rhs.m_outer_it and
153
- lhs.m_inner .begin () == rhs.m_inner .begin ();
154
- }
155
- friend constexpr auto operator ==(join_iterator const & lhs, std::default_sentinel_t ) -> bool {
156
- return lhs.m_outer_it == lhs.m_outer_last ;
157
- }
158
-
159
- private:
160
- constexpr auto normalize () & -> void {
161
- while (containers::is_empty (m_inner)) {
162
- ++m_outer_it;
163
- if (m_outer_it == m_outer_last) {
164
- return ;
165
- }
166
- m_inner.set (m_outer_it);
167
- }
168
- }
169
-
170
- Iterator m_outer_it;
171
- Sentinel m_outer_last;
172
- inner_range_iterator<iter_reference_t <Iterator>> m_inner;
173
- };
174
-
175
22
export template <range Range>
176
- struct join {
177
- explicit constexpr join (Range && range):
178
- m_range(OPERATORS_FORWARD(range))
179
- {
180
- }
181
- constexpr auto begin () const & requires std::is_reference_v<range_reference_t<Range>> {
182
- return join_iterator (
183
- containers::begin (m_range),
184
- containers::end (m_range),
185
- m_inner
186
- );
187
- }
188
- constexpr auto begin () & requires std::is_reference_v<range_reference_t<Range>> {
189
- return join_iterator (
190
- containers::begin (m_range),
191
- containers::end (m_range),
192
- m_inner
193
- );
194
- }
195
- constexpr auto begin () && {
196
- return join_iterator (
197
- containers::begin (std::move (m_range)),
198
- containers::end (std::move (m_range)),
199
- m_inner
200
- );
201
- }
202
- // TODO: Support bidirectional?
203
- static constexpr auto end () {
204
- return std::default_sentinel;
205
- }
206
- private:
207
- [[no_unique_address]] Range m_range;
208
- [[no_unique_address]] inner_range<range_reference_t <Range>> m_inner;
209
- };
23
+ constexpr auto join (Range && r) {
24
+ using value_type = containers::range_value_t <containers::range_value_t <Range>>;
25
+ return ::containers::join_with (
26
+ OPERATORS_FORWARD (r),
27
+ containers::array<value_type, 0_bi>()
28
+ );
29
+ }
210
30
211
31
} // namespace containers
0 commit comments