xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.join/range.join.iterator/increment.pass.cpp (revision 6a664674990094c1b5d2e717256f08cb04485899)
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 
11 // constexpr iterator& operator++();
12 // constexpr void operator++(int);
13 // constexpr iterator operator++(int)
14 //            requires ref-is-glvalue && forward_range<Base> &&
15 //                     forward_range<range_reference_t<Base>>;
16 
17 #include <cassert>
18 #include <ranges>
19 
20 #include "test_macros.h"
21 #include "../types.h"
22 
test()23 constexpr bool test() {
24   // This way if we read past end we'll catch the error.
25   int buffer1[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
26   int dummy = 42;
27   (void) dummy;
28   int buffer2[2][4] = {{9, 10, 11, 12}, {13, 14, 15, 16}};
29 
30   // operator++(int);
31   {
32     std::ranges::join_view jv(buffer1);
33     auto iter = jv.begin();
34     for (int i = 1; i < 9; ++i) {
35       assert(*iter++ == i);
36     }
37   }
38 
39   {
40     using IntView = ValueView<int>;
41     IntView children[4] = {IntView(buffer1[0]), IntView(buffer1[1]), IntView(buffer2[0]), IntView(buffer2[1])};
42     std::ranges::join_view jv(ValueView<IntView>{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     using IntView = ValueView<int>;
157     IntView children[4] = {IntView(buffer1[0]), IntView(buffer1[1]), IntView(buffer2[0]), IntView(buffer2[1])};
158     std::ranges::join_view jv(ValueView<IntView>{children});
159     auto iter = jv.begin();
160     for (int i = 2; i < 17; ++i) {
161       assert(*++iter == i);
162     }
163 
164     ASSERT_SAME_TYPE(decltype(++iter), decltype(iter)&);
165   }
166 
167   {
168     // check return value
169     std::ranges::join_view jv(buffer1);
170     auto iter = jv.begin();
171     using iterator = decltype(iter);
172 
173     decltype(auto) iter2 = ++iter;
174     static_assert(std::is_same_v<decltype(iter2), iterator&>);
175     assert(&iter2 == &iter);
176 
177     std::same_as<iterator> decltype(auto) iter3 = iter++;
178     assert(std::next(iter3) == iter);
179   }
180 
181   {
182     // !ref-is-glvalue
183     BidiCommonInner inners[2] = {buffer1[0], buffer1[1]};
184     InnerRValue<BidiCommonOuter<BidiCommonInner>> outer{inners};
185     std::ranges::join_view jv(outer);
186     auto iter = jv.begin();
187     static_assert(std::is_void_v<decltype(iter++)>);
188   }
189 
190   {
191     // !forward_range<Base>
192     BufferView<int*> inners[2] = {buffer1[0], buffer1[1]};
193     using Outer = SimpleInputCommonOuter<BufferView<int*>>;
194     std::ranges::join_view jv{Outer(inners)};
195     auto iter = jv.begin();
196     static_assert(std::is_void_v<decltype(iter++)>);
197   }
198 
199   {
200     // !forward_range<range_reference_t<Base>>
201     InputCommonInner inners[1] = {buffer1[0]};
202     std::ranges::join_view jv{inners};
203     auto iter = jv.begin();
204     static_assert(std::is_void_v<decltype(iter++)>);
205   }
206 
207   {
208     // Check stashing iterators (LWG3698: regex_iterator and join_view don't work together very well)
209     std::ranges::join_view<StashingRange> jv;
210     auto it = jv.begin();
211     assert(*it == 'a');
212     ++it;
213     assert(*it == 'a');
214     ++it;
215     assert(*it == 'b');
216     it++;
217     assert(*it == 'a');
218     it++;
219     assert(*it == 'b');
220     ++it;
221     assert(*it == 'c');
222   }
223 
224   return true;
225 }
226 
main(int,char **)227 int main(int, char**) {
228   test();
229   static_assert(test());
230 
231   return 0;
232 }
233