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
23constexpr 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
227int main(int, char**) {
228 test();
229 static_assert(test());
230
231 return 0;
232}
233

source code of libcxx/test/std/ranges/range.adaptors/range.join/range.join.iterator/increment.pass.cpp