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 iterator& operator++();
13 // constexpr void operator++(int);
14 // constexpr iterator operator++(int)
15 //            requires ref-is-glvalue && forward_­range<Base> &&
16 //                     forward_range<range_reference_t<Base>>;
17 
18 #include <cassert>
19 #include <ranges>
20 
21 #include "test_macros.h"
22 #include "../types.h"
23 
test()24 constexpr bool test() {
25   // This way if we read past end we'll catch the error.
26   int buffer1[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
27   int dummy = 42;
28   (void) dummy;
29   int buffer2[2][4] = {{9, 10, 11, 12}, {13, 14, 15, 16}};
30 
31   // operator++(int);
32   {
33     std::ranges::join_view jv(buffer1);
34     auto iter = jv.begin();
35     for (int i = 1; i < 9; ++i) {
36       assert(*iter++ == i);
37     }
38   }
39 
40   {
41     ValueView<int> children[4] = {ValueView(buffer1[0]), ValueView(buffer1[1]), ValueView(buffer2[0]), ValueView(buffer2[1])};
42     std::ranges::join_view jv(ValueView<ValueView<int>>{children});
43     auto iter = jv.begin();
44     for (int i = 1; i < 17; ++i) {
45       assert(*iter == i);
46       iter++;
47     }
48 
49     ASSERT_SAME_TYPE(decltype(iter++), void);
50   }
51 
52   {
53     std::ranges::join_view jv(buffer1);
54     auto iter = std::next(jv.begin(), 7);
55     assert(*iter++ == 8);
56     assert(iter == jv.end());
57   }
58 
59   {
60     int small[2][1] = {{1}, {2}};
61     std::ranges::join_view jv(small);
62     auto iter = jv.begin();
63     for (int i = 1; i < 3; ++i) {
64       assert(*iter++ == i);
65     }
66   }
67 
68   // Has some empty children.
69   {
70     CopyableChild children[4] = {CopyableChild(buffer1[0], 4), CopyableChild(buffer1[1], 0), CopyableChild(buffer2[0], 1), CopyableChild(buffer2[1], 0)};
71     auto jv = std::ranges::join_view(ParentView(children));
72     auto iter = jv.begin();
73     assert(*iter == 1); iter++;
74     assert(*iter == 2); iter++;
75     assert(*iter == 3); iter++;
76     assert(*iter == 4); iter++;
77     assert(*iter == 9); iter++;
78     assert(iter == jv.end());
79   }
80 
81   // Parent is empty.
82   {
83     CopyableChild children[4] = {CopyableChild(buffer1[0]), CopyableChild(buffer1[1]), CopyableChild(buffer2[0]), CopyableChild(buffer2[1])};
84     std::ranges::join_view jv(ParentView(children, 0));
85     assert(jv.begin() == jv.end());
86   }
87 
88   // Parent size is one.
89   {
90     CopyableChild children[1] = {CopyableChild(buffer1[0])};
91     std::ranges::join_view jv(ParentView(children, 1));
92     auto iter = jv.begin();
93     assert(*iter == 1); iter++;
94     assert(*iter == 2); iter++;
95     assert(*iter == 3); iter++;
96     assert(*iter == 4); iter++;
97     assert(iter == jv.end());
98   }
99 
100   // Parent and child size is one.
101   {
102     CopyableChild children[1] = {CopyableChild(buffer1[0], 1)};
103     std::ranges::join_view jv(ParentView(children, 1));
104     auto iter = jv.begin();
105     assert(*iter == 1); iter++;
106     assert(iter == jv.end());
107   }
108 
109   // Parent size is one child is empty
110   {
111     CopyableChild children[1] = {CopyableChild(buffer1[0], 0)};
112     std::ranges::join_view jv(ParentView(children, 1));
113     assert(jv.begin() == jv.end());
114   }
115 
116   // Has all empty children.
117   {
118     CopyableChild children[4] = {CopyableChild(buffer1[0], 0), CopyableChild(buffer1[1], 0), CopyableChild(buffer2[0], 0), CopyableChild(buffer2[1], 0)};
119     auto jv = std::ranges::join_view(ParentView(children));
120     assert(jv.begin() == jv.end());
121   }
122 
123   // First child is empty, others are not.
124   {
125     CopyableChild children[4] = {CopyableChild(buffer1[0], 4), CopyableChild(buffer1[1], 0), CopyableChild(buffer2[0], 0), CopyableChild(buffer2[1], 0)};
126     auto jv = std::ranges::join_view(ParentView(children));
127     auto iter = jv.begin();
128     assert(*iter == 1); iter++;
129     assert(*iter == 2); iter++;
130     assert(*iter == 3); iter++;
131     assert(*iter == 4); iter++;
132     assert(iter == jv.end());
133   }
134 
135   // Last child is empty, others are not.
136   {
137     CopyableChild children[4] = {CopyableChild(buffer1[0], 4), CopyableChild(buffer1[1], 4), CopyableChild(buffer2[0], 4), CopyableChild(buffer2[1], 0)};
138     auto jv = std::ranges::join_view(ParentView(children));
139     auto iter = jv.begin();
140     for (int i = 1; i < 13; ++i) {
141       assert(*iter == i);
142       iter++;
143     }
144   }
145 
146   // operator++();
147   {
148     std::ranges::join_view jv(buffer1);
149     auto iter = jv.begin();
150     for (int i = 2; i < 9; ++i) {
151       assert(*++iter == i);
152     }
153   }
154 
155   {
156     ValueView<int> children[4] = {ValueView(buffer1[0]), ValueView(buffer1[1]), ValueView(buffer2[0]), ValueView(buffer2[1])};
157     std::ranges::join_view jv(ValueView<ValueView<int>>{children});
158     auto iter = jv.begin();
159     for (int i = 2; i < 17; ++i) {
160       assert(*++iter == i);
161     }
162 
163     ASSERT_SAME_TYPE(decltype(++iter), decltype(iter)&);
164   }
165 
166   {
167     // check return value
168     std::ranges::join_view jv(buffer1);
169     auto iter = jv.begin();
170     using iterator = decltype(iter);
171 
172     decltype(auto) iter2 = ++iter;
173     static_assert(std::is_same_v<decltype(iter2), iterator&>);
174     assert(&iter2 == &iter);
175 
176     std::same_as<iterator> decltype(auto) iter3 = iter++;
177     assert(std::next(iter3) == iter);
178   }
179 
180   {
181     // !ref-is-glvalue
182     BidiCommonInner inners[2] = {buffer1[0], buffer1[1]};
183     InnerRValue<BidiCommonOuter<BidiCommonInner>> outer{inners};
184     std::ranges::join_view jv(outer);
185     auto iter = jv.begin();
186     static_assert(std::is_void_v<decltype(iter++)>);
187   }
188 
189   {
190     // !forward_­range<Base>
191     BufferView<int*> inners[2] = {buffer1[0], buffer1[1]};
192     using Outer = SimpleInputCommonOuter<BufferView<int*>>;
193     std::ranges::join_view jv{Outer(inners)};
194     auto iter = jv.begin();
195     static_assert(std::is_void_v<decltype(iter++)>);
196   }
197 
198   {
199     // !forward_range<range_reference_t<Base>>
200     InputCommonInner inners[1] = {buffer1[0]};
201     std::ranges::join_view jv{inners};
202     auto iter = jv.begin();
203     static_assert(std::is_void_v<decltype(iter++)>);
204   }
205 
206   return true;
207 }
208 
main(int,char **)209 int main(int, char**) {
210   test();
211   static_assert(test());
212 
213   return 0;
214 }
215