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