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