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