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, c++20
10 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11 
12 // test if zip_view models input_range, forward_range, bidirectional_range,
13 //                         random_access_range, contiguous_range, common_range
14 //                         sized_range
15 
16 #include <cassert>
17 #include <concepts>
18 #include <ranges>
19 #include <tuple>
20 #include <utility>
21 
22 #include "types.h"
23 
24 void testConceptPair() {
25   int buffer1[2] = {1, 2};
26   int buffer2[3] = {1, 2, 3};
27   {
28     std::ranges::zip_view v{ContiguousCommonView{buffer1}, ContiguousCommonView{buffer2}};
29     using View = decltype(v);
30     static_assert(std::ranges::random_access_range<View>);
31     static_assert(!std::ranges::contiguous_range<View>);
32     static_assert(std::ranges::common_range<View>);
33     static_assert(std::ranges::sized_range<View>);
34   }
35 
36   {
37     std::ranges::zip_view v{ContiguousNonCommonView{buffer1}, ContiguousNonCommonView{buffer2}};
38     using View = decltype(v);
39     static_assert(std::ranges::random_access_range<View>);
40     static_assert(!std::ranges::contiguous_range<View>);
41     static_assert(!std::ranges::common_range<View>);
42     static_assert(!std::ranges::sized_range<View>);
43   }
44 
45   {
46     std::ranges::zip_view v{ContiguousNonCommonSized{buffer1}, ContiguousNonCommonSized{buffer2}};
47     using View = decltype(v);
48     static_assert(std::ranges::random_access_range<View>);
49     static_assert(!std::ranges::contiguous_range<View>);
50     static_assert(std::ranges::common_range<View>);
51     static_assert(std::ranges::sized_range<View>);
52   }
53 
54   {
55     std::ranges::zip_view v{SizedRandomAccessView{buffer1}, ContiguousCommonView{buffer2}};
56     using View = decltype(v);
57     static_assert(std::ranges::random_access_range<View>);
58     static_assert(!std::ranges::contiguous_range<View>);
59     static_assert(std::ranges::common_range<View>);
60     static_assert(std::ranges::sized_range<View>);
61   }
62 
63   {
64     std::ranges::zip_view v{SizedRandomAccessView{buffer1}, SizedRandomAccessView{buffer2}};
65     using View = decltype(v);
66     static_assert(std::ranges::random_access_range<View>);
67     static_assert(!std::ranges::contiguous_range<View>);
68     static_assert(std::ranges::common_range<View>);
69     static_assert(std::ranges::sized_range<View>);
70   }
71 
72   {
73     std::ranges::zip_view v{NonSizedRandomAccessView{buffer1}, NonSizedRandomAccessView{buffer2}};
74     using View = decltype(v);
75     static_assert(std::ranges::random_access_range<View>);
76     static_assert(!std::ranges::contiguous_range<View>);
77     static_assert(!std::ranges::common_range<View>);
78     static_assert(!std::ranges::sized_range<View>);
79   }
80 
81   {
82     std::ranges::zip_view v{BidiCommonView{buffer1}, SizedRandomAccessView{buffer2}};
83     using View = decltype(v);
84     static_assert(std::ranges::bidirectional_range<View>);
85     static_assert(!std::ranges::random_access_range<View>);
86     static_assert(!std::ranges::common_range<View>);
87     static_assert(!std::ranges::sized_range<View>);
88   }
89 
90   {
91     std::ranges::zip_view v{BidiCommonView{buffer1}, BidiCommonView{buffer2}};
92     using View = decltype(v);
93     static_assert(std::ranges::bidirectional_range<View>);
94     static_assert(!std::ranges::random_access_range<View>);
95     static_assert(!std::ranges::common_range<View>);
96     static_assert(!std::ranges::sized_range<View>);
97   }
98 
99   {
100     std::ranges::zip_view v{BidiCommonView{buffer1}, ForwardSizedView{buffer2}};
101     using View = decltype(v);
102     static_assert(std::ranges::forward_range<View>);
103     static_assert(!std::ranges::bidirectional_range<View>);
104     static_assert(std::ranges::common_range<View>);
105     static_assert(!std::ranges::sized_range<View>);
106   }
107 
108   {
109     std::ranges::zip_view v{BidiNonCommonView{buffer1}, ForwardSizedView{buffer2}};
110     using View = decltype(v);
111     static_assert(std::ranges::forward_range<View>);
112     static_assert(!std::ranges::bidirectional_range<View>);
113     static_assert(!std::ranges::common_range<View>);
114     static_assert(!std::ranges::sized_range<View>);
115   }
116 
117   {
118     std::ranges::zip_view v{ForwardSizedView{buffer1}, ForwardSizedView{buffer2}};
119     using View = decltype(v);
120     static_assert(std::ranges::forward_range<View>);
121     static_assert(!std::ranges::bidirectional_range<View>);
122     static_assert(std::ranges::common_range<View>);
123     static_assert(std::ranges::sized_range<View>);
124   }
125 
126   {
127     std::ranges::zip_view v{ForwardSizedNonCommon{buffer1}, ForwardSizedView{buffer2}};
128     using View = decltype(v);
129     static_assert(std::ranges::forward_range<View>);
130     static_assert(!std::ranges::bidirectional_range<View>);
131     static_assert(!std::ranges::common_range<View>);
132     static_assert(std::ranges::sized_range<View>);
133   }
134 
135   {
136     std::ranges::zip_view v{InputCommonView{buffer1}, ForwardSizedView{buffer2}};
137     using View = decltype(v);
138     static_assert(std::ranges::input_range<View>);
139     static_assert(!std::ranges::forward_range<View>);
140     static_assert(std::ranges::common_range<View>);
141     static_assert(!std::ranges::sized_range<View>);
142   }
143 
144   {
145     std::ranges::zip_view v{InputCommonView{buffer1}, InputCommonView{buffer2}};
146     using View = decltype(v);
147     static_assert(std::ranges::input_range<View>);
148     static_assert(!std::ranges::forward_range<View>);
149     static_assert(std::ranges::common_range<View>);
150     static_assert(!std::ranges::sized_range<View>);
151   }
152 
153   {
154     std::ranges::zip_view v{InputNonCommonView{buffer1}, InputCommonView{buffer2}};
155     using View = decltype(v);
156     static_assert(std::ranges::input_range<View>);
157     static_assert(!std::ranges::forward_range<View>);
158     static_assert(!std::ranges::common_range<View>);
159     static_assert(!std::ranges::sized_range<View>);
160   }
161 }
162 
163 void testConceptTuple() {
164   int buffer1[2] = {1, 2};
165   int buffer2[3] = {1, 2, 3};
166   int buffer3[4] = {1, 2, 3, 4};
167 
168   // TODO: uncomment all the static_asserts once [tuple.tuple] section in P2321R2 is implemented
169   // This is because convertible_to<tuple<int&,int&,int&>&, tuple<int,int,int>> is false without
170   // the above implementation, thus the zip iterator does not model indirectly_readable
171 
172   {
173     std::ranges::zip_view v{ContiguousCommonView{buffer1}, ContiguousCommonView{buffer2},
174                             ContiguousCommonView{buffer3}};
175     using View = decltype(v);
176     //  static_assert(std::ranges::random_access_range<View>);
177     static_assert(!std::ranges::contiguous_range<View>);
178     static_assert(std::ranges::common_range<View>);
179     static_assert(std::ranges::sized_range<View>);
180   }
181 
182   {
183     std::ranges::zip_view v{ContiguousNonCommonView{buffer1}, ContiguousNonCommonView{buffer2},
184                             ContiguousNonCommonView{buffer3}};
185     using View = decltype(v);
186     //  static_assert(std::ranges::random_access_range<View>);
187     static_assert(!std::ranges::contiguous_range<View>);
188     static_assert(!std::ranges::common_range<View>);
189     static_assert(!std::ranges::sized_range<View>);
190   }
191 
192   {
193     std::ranges::zip_view v{ContiguousNonCommonSized{buffer1}, ContiguousNonCommonSized{buffer2},
194                             ContiguousNonCommonSized{buffer3}};
195     using View = decltype(v);
196     //   static_assert(std::ranges::random_access_range<View>);
197     static_assert(!std::ranges::contiguous_range<View>);
198     static_assert(std::ranges::common_range<View>);
199     static_assert(std::ranges::sized_range<View>);
200   }
201 
202   {
203     std::ranges::zip_view v{SizedRandomAccessView{buffer1}, ContiguousCommonView{buffer2},
204                             ContiguousCommonView{buffer3}};
205     using View = decltype(v);
206     //  static_assert(std::ranges::random_access_range<View>);
207     static_assert(!std::ranges::contiguous_range<View>);
208     static_assert(std::ranges::common_range<View>);
209     static_assert(std::ranges::sized_range<View>);
210   }
211 
212   {
213     std::ranges::zip_view v{SizedRandomAccessView{buffer1}, SizedRandomAccessView{buffer2},
214                             SizedRandomAccessView{buffer3}};
215     using View = decltype(v);
216     //  static_assert(std::ranges::random_access_range<View>);
217     static_assert(!std::ranges::contiguous_range<View>);
218     static_assert(std::ranges::common_range<View>);
219     static_assert(std::ranges::sized_range<View>);
220   }
221 
222   {
223     std::ranges::zip_view v{NonSizedRandomAccessView{buffer1}, NonSizedRandomAccessView{buffer2},
224                             NonSizedRandomAccessView{buffer3}};
225     using View = decltype(v);
226     //  static_assert(std::ranges::random_access_range<View>);
227     static_assert(!std::ranges::contiguous_range<View>);
228     static_assert(!std::ranges::common_range<View>);
229     static_assert(!std::ranges::sized_range<View>);
230   }
231 
232   {
233     std::ranges::zip_view v{BidiCommonView{buffer1}, SizedRandomAccessView{buffer2}, SizedRandomAccessView{buffer3}};
234     using View = decltype(v);
235     //  static_assert(std::ranges::bidirectional_range<View>);
236     static_assert(!std::ranges::random_access_range<View>);
237     static_assert(!std::ranges::common_range<View>);
238     static_assert(!std::ranges::sized_range<View>);
239   }
240 
241   {
242     std::ranges::zip_view v{BidiCommonView{buffer1}, BidiCommonView{buffer2}, BidiCommonView{buffer3}};
243     using View = decltype(v);
244     //  static_assert(std::ranges::bidirectional_range<View>);
245     static_assert(!std::ranges::random_access_range<View>);
246     static_assert(!std::ranges::common_range<View>);
247     static_assert(!std::ranges::sized_range<View>);
248   }
249 
250   {
251     std::ranges::zip_view v{BidiCommonView{buffer1}, ForwardSizedView{buffer2}, ForwardSizedView{buffer3}};
252     using View = decltype(v);
253     //  static_assert(std::ranges::forward_range<View>);
254     static_assert(!std::ranges::bidirectional_range<View>);
255     static_assert(std::ranges::common_range<View>);
256     static_assert(!std::ranges::sized_range<View>);
257   }
258 
259   {
260     std::ranges::zip_view v{BidiNonCommonView{buffer1}, ForwardSizedView{buffer2}, ForwardSizedView{buffer3}};
261     using View = decltype(v);
262     //  static_assert(std::ranges::forward_range<View>);
263     static_assert(!std::ranges::bidirectional_range<View>);
264     static_assert(!std::ranges::common_range<View>);
265     static_assert(!std::ranges::sized_range<View>);
266   }
267 
268   {
269     std::ranges::zip_view v{ForwardSizedView{buffer1}, ForwardSizedView{buffer2}, ForwardSizedView{buffer3}};
270     using View = decltype(v);
271     //  static_assert(std::ranges::forward_range<View>);
272     static_assert(!std::ranges::bidirectional_range<View>);
273     static_assert(std::ranges::common_range<View>);
274     static_assert(std::ranges::sized_range<View>);
275   }
276 
277   {
278     std::ranges::zip_view v{ForwardSizedNonCommon{buffer1}, ForwardSizedView{buffer2}, ForwardSizedView{buffer3}};
279     using View = decltype(v);
280     // static_assert(std::ranges::forward_range<View>);
281     static_assert(!std::ranges::bidirectional_range<View>);
282     static_assert(!std::ranges::common_range<View>);
283     static_assert(std::ranges::sized_range<View>);
284   }
285 
286   {
287     std::ranges::zip_view v{InputCommonView{buffer1}, ForwardSizedView{buffer2}, ForwardSizedView{buffer3}};
288     using View = decltype(v);
289     //  static_assert(std::ranges::input_range<View>);
290     static_assert(!std::ranges::forward_range<View>);
291     static_assert(std::ranges::common_range<View>);
292     static_assert(!std::ranges::sized_range<View>);
293   }
294 
295   {
296     std::ranges::zip_view v{InputCommonView{buffer1}, InputCommonView{buffer2}, InputCommonView{buffer3}};
297     using View = decltype(v);
298     //   static_assert(std::ranges::input_range<View>);
299     static_assert(!std::ranges::forward_range<View>);
300     static_assert(std::ranges::common_range<View>);
301     static_assert(!std::ranges::sized_range<View>);
302   }
303 
304   {
305     std::ranges::zip_view v{InputNonCommonView{buffer1}, InputCommonView{buffer2}, InputCommonView{buffer3}};
306     using View = decltype(v);
307     //   static_assert(std::ranges::input_range<View>);
308     static_assert(!std::ranges::forward_range<View>);
309     static_assert(!std::ranges::common_range<View>);
310     static_assert(!std::ranges::sized_range<View>);
311   }
312 }
313 
314 using OutputIter = cpp17_output_iterator<int*>;
315 static_assert(std::output_iterator<OutputIter, int>);
316 
317 struct OutputView : std::ranges::view_base {
318   OutputIter begin() const;
319   sentinel_wrapper<OutputIter> end() const;
320 };
321 static_assert(std::ranges::output_range<OutputView, int>);
322 static_assert(!std::ranges::input_range<OutputView>);
323 
324 template <class... Ts>
325 concept zippable = requires {
326   typename std::ranges::zip_view<Ts...>;
327 };
328 
329 // output_range is not supported
330 static_assert(!zippable<OutputView>);
331 static_assert(!zippable<SimpleCommon, OutputView>);
332 static_assert(zippable<SimpleCommon>);
333