1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11
12 // constexpr auto end();
13 // constexpr auto end() const;
14
15 #include <cassert>
16 #include <ranges>
17 #include <type_traits>
18
19 #include "test_macros.h"
20 #include "types.h"
21
22 template <class T>
23 concept HasConstEnd = requires (const T& t){
24 t.end();
25 };
26
27
28 // | ID | outer | outer | outer | inner | inner | inner | end() | end() |
29 // | | simple | forward | common | l_ref | forward | common | | const |
30 // |----|--------|---------|--------|-------|---------|--------|---------------|--------------|
31 // | 1 | Y | Y | Y | Y | Y | Y |iterator<true> |iterator<true>|
32 // | 2 | Y | Y | Y | Y | Y | N |sentinel<true> |sentinel<true>|
33 // | 3 | Y | Y | Y | Y | N | Y |sentinel<true> |sentinel<true>|
34 // | 4 | Y | Y | Y | N | Y | Y |sentinel<true> | - |
35 // | 5 | Y | Y | N | Y | Y | Y |sentinel<true> |sentinel<true>|
36 // | 6 | Y | N | Y | Y | Y | Y |sentinel<true> |sentinel<true>|
37 // | 7 | N | Y | Y | Y | Y | Y |iterator<false>|iterator<true>|
38 // | 8 | N | Y | Y | Y | Y | N |sentinel<false>|sentinel<true>|
39 // | 9 | N | Y | Y | Y | N | Y |sentinel<false>|sentinel<true>|
40 // | 10 | N | Y | Y | N | Y | Y |sentinel<false>| - |
41 // | 11 | N | Y | N | Y | Y | Y |sentinel<false>|sentinel<true>|
42 // | 12 | N | N | Y | Y | Y | Y |sentinel<false>|sentinel<true>|
43 //
44 //
45
46 struct ConstNotRange : std::ranges::view_base {
47 const ChildView* begin();
48 const ChildView* end();
49 };
50
test()51 constexpr bool test() {
52 int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
53
54 {
55 // test ID 1
56 ForwardCommonInner inners[4] = {buffer[0], buffer[1], buffer[2], buffer[3]};
57 SimpleForwardCommonOuter<ForwardCommonInner> outer{inners};
58
59 std::ranges::join_view jv(outer);
60 assert(jv.end() == std::ranges::next(jv.begin(), 16));
61 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 16));
62
63 static_assert(HasConstEnd<decltype(jv)>);
64 static_assert(std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);
65 static_assert(std::ranges::common_range<decltype(jv)>);
66 static_assert(std::ranges::common_range<const decltype(jv)>);
67 }
68
69 {
70 // test ID 2
71 ForwardNonCommonInner inners[3] = {buffer[0], buffer[1], buffer[2]};
72 SimpleForwardCommonOuter<ForwardNonCommonInner> outer{inners};
73
74 std::ranges::join_view jv(outer);
75 assert(jv.end() == std::ranges::next(jv.begin(), 12));
76 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 12));
77
78 static_assert(HasConstEnd<decltype(jv)>);
79 static_assert(std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);
80 static_assert(!std::ranges::common_range<decltype(jv)>);
81 static_assert(!std::ranges::common_range<const decltype(jv)>);
82 }
83
84 {
85 // test ID 3
86 InputCommonInner inners[3] = {buffer[0], buffer[1], buffer[2]};
87 SimpleForwardCommonOuter<InputCommonInner> outer{inners};
88
89 std::ranges::join_view jv(outer);
90 assert(jv.end() == std::ranges::next(jv.begin(), 12));
91 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 12));
92
93 static_assert(HasConstEnd<decltype(jv)>);
94 static_assert(std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);
95 static_assert(!std::ranges::common_range<decltype(jv)>);
96 static_assert(!std::ranges::common_range<const decltype(jv)>);
97 }
98
99 {
100 // test ID 4
101 ForwardCommonInner inners[2] = {buffer[0], buffer[1]};
102 InnerRValue<SimpleForwardCommonOuter<ForwardCommonInner>> outer{inners};
103
104 std::ranges::join_view jv(outer);
105 assert(jv.end() == std::ranges::next(jv.begin(), 8));
106
107 static_assert(!HasConstEnd<decltype(jv)>);
108 static_assert(!std::ranges::common_range<decltype(jv)>);
109 static_assert(!std::ranges::common_range<const decltype(jv)>);
110 }
111
112 {
113 // test ID 5
114 ForwardCommonInner inners[4] = {buffer[0], buffer[1], buffer[2], buffer[3]};
115 SimpleForwardNonCommonOuter<ForwardCommonInner> outer{inners};
116
117 std::ranges::join_view jv(outer);
118 assert(jv.end() == std::ranges::next(jv.begin(), 16));
119 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 16));
120
121 static_assert(HasConstEnd<decltype(jv)>);
122 static_assert(std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);
123 static_assert(!std::ranges::common_range<decltype(jv)>);
124 static_assert(!std::ranges::common_range<const decltype(jv)>);
125 }
126
127 {
128 // test ID 6
129 ForwardCommonInner inners[4] = {buffer[0], buffer[1], buffer[2], buffer[3]};
130 SimpleInputCommonOuter<ForwardCommonInner> outer{inners};
131
132 std::ranges::join_view jv(outer);
133 assert(jv.end() == std::ranges::next(jv.begin(), 16));
134 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 16));
135
136 static_assert(HasConstEnd<decltype(jv)>);
137 static_assert(std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);
138 static_assert(!std::ranges::common_range<decltype(jv)>);
139 static_assert(!std::ranges::common_range<const decltype(jv)>);
140 }
141
142 {
143 // test ID 7
144 ForwardCommonInner inners[1] = {buffer[0]};
145 NonSimpleForwardCommonOuter<ForwardCommonInner> outer{inners};
146
147 std::ranges::join_view jv(outer);
148 assert(jv.end() == std::ranges::next(jv.begin(), 4));
149 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 4));
150
151 static_assert(HasConstEnd<decltype(jv)>);
152 static_assert(!std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);
153 static_assert(std::ranges::common_range<decltype(jv)>);
154 static_assert(std::ranges::common_range<const decltype(jv)>);
155 }
156
157 {
158 // test ID 8
159 ForwardNonCommonInner inners[3] = {buffer[0], buffer[1], buffer[2]};
160 NonSimpleForwardCommonOuter<ForwardNonCommonInner> outer{inners};
161
162 std::ranges::join_view jv(outer);
163 assert(jv.end() == std::ranges::next(jv.begin(), 12));
164 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 12));
165
166 static_assert(HasConstEnd<decltype(jv)>);
167 static_assert(!std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);
168 static_assert(!std::ranges::common_range<decltype(jv)>);
169 static_assert(!std::ranges::common_range<const decltype(jv)>);
170 }
171
172 {
173 // test ID 9
174 InputCommonInner inners[3] = {buffer[0], buffer[1], buffer[2]};
175 NonSimpleForwardCommonOuter<InputCommonInner> outer{inners};
176
177 std::ranges::join_view jv(outer);
178 assert(jv.end() == std::ranges::next(jv.begin(), 12));
179 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 12));
180
181 static_assert(HasConstEnd<decltype(jv)>);
182 static_assert(!std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);
183 static_assert(!std::ranges::common_range<decltype(jv)>);
184 static_assert(!std::ranges::common_range<const decltype(jv)>);
185 }
186
187 {
188 // test ID 10
189 ForwardCommonInner inners[2] = {buffer[0], buffer[1]};
190 InnerRValue<NonSimpleForwardCommonOuter<ForwardCommonInner>> outer{inners};
191
192 std::ranges::join_view jv(outer);
193 assert(jv.end() == std::ranges::next(jv.begin(), 8));
194
195 static_assert(!HasConstEnd<decltype(jv)>);
196 static_assert(!std::ranges::common_range<decltype(jv)>);
197 static_assert(!std::ranges::common_range<const decltype(jv)>);
198 }
199
200 {
201 // test ID 11
202 ForwardCommonInner inners[4] = {buffer[0], buffer[1], buffer[2], buffer[3]};
203 NonSimpleForwardNonCommonOuter<ForwardCommonInner> outer{inners};
204
205 std::ranges::join_view jv(outer);
206 assert(jv.end() == std::ranges::next(jv.begin(), 16));
207 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 16));
208
209 static_assert(HasConstEnd<decltype(jv)>);
210 static_assert(!std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);
211 static_assert(!std::ranges::common_range<decltype(jv)>);
212 static_assert(!std::ranges::common_range<const decltype(jv)>);
213 }
214
215 {
216 // test ID 12
217 ForwardCommonInner inners[4] = {buffer[0], buffer[1], buffer[2], buffer[3]};
218 NonSimpleInputCommonOuter<ForwardCommonInner> outer{inners};
219
220 std::ranges::join_view jv(outer);
221 assert(jv.end() == std::ranges::next(jv.begin(), 16));
222 assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 16));
223
224 static_assert(HasConstEnd<decltype(jv)>);
225 static_assert(!std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>);
226 static_assert(!std::ranges::common_range<decltype(jv)>);
227 static_assert(!std::ranges::common_range<const decltype(jv)>);
228 }
229
230 {
231 std::ranges::join_view jv(ConstNotRange{});
232 static_assert(!HasConstEnd<decltype(jv)>);
233 }
234
235 // Has some empty children.
236 {
237 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 1), CopyableChild(buffer[3], 0)};
238 auto jv = std::ranges::join_view(ParentView(children));
239 assert(jv.end() == std::ranges::next(jv.begin(), 5));
240 }
241
242 // Parent is empty.
243 {
244 CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
245 std::ranges::join_view jv(ParentView(children, 0));
246 assert(jv.end() == jv.begin());
247 }
248
249 // Parent size is one.
250 {
251 CopyableChild children[1] = {CopyableChild(buffer[0])};
252 std::ranges::join_view jv(ParentView(children, 1));
253 assert(jv.end() == std::ranges::next(jv.begin(), 4));
254 }
255
256 // Parent and child size is one.
257 {
258 CopyableChild children[1] = {CopyableChild(buffer[0], 1)};
259 std::ranges::join_view jv(ParentView(children, 1));
260 assert(jv.end() == std::ranges::next(jv.begin()));
261 }
262
263 // Parent size is one child is empty
264 {
265 CopyableChild children[1] = {CopyableChild(buffer[0], 0)};
266 std::ranges::join_view jv(ParentView(children, 1));
267 assert(jv.end() == jv.begin());
268 }
269
270 // Has all empty children.
271 {
272 CopyableChild children[4] = {CopyableChild(buffer[0], 0), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0), CopyableChild(buffer[3], 0)};
273 auto jv = std::ranges::join_view(ParentView(children));
274 assert(jv.end() == jv.begin());
275 }
276
277 // First child is empty, others are not.
278 {
279 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0), CopyableChild(buffer[3], 0)};
280 auto jv = std::ranges::join_view(ParentView(children));
281 assert(jv.end() == std::ranges::next(jv.begin(), 4));
282 }
283
284 // Last child is empty, others are not.
285 {
286 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 4), CopyableChild(buffer[2], 4), CopyableChild(buffer[3], 0)};
287 auto jv = std::ranges::join_view(ParentView(children));
288 assert(jv.end() == std::ranges::next(jv.begin(), 12));
289 }
290
291 return true;
292 }
293
main(int,char **)294 int main(int, char**) {
295 test();
296 static_assert(test());
297
298 return 0;
299 }
300