1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <algorithm>
18 #include <forward_list>
19 #include <list>
20 #include <type_traits>
21 #include <vector>
22
23 #include "gtest/gtest.h"
24 #include "transform_iterator.h"
25
26 namespace art {
27
28 namespace { // anonymous namespace
29
30 struct ValueHolder {
31 // Deliberately not explicit.
ValueHolderart::__anone6f0977f0111::ValueHolder32 ValueHolder(int v) : value(v) { } // NOLINT
33 int value;
34 };
35
operator ==(const ValueHolder & lhs,const ValueHolder & rhs)36 bool operator==(const ValueHolder& lhs, const ValueHolder& rhs) {
37 return lhs.value == rhs.value;
38 }
39
40 } // anonymous namespace
41
TEST(TransformIterator,VectorAdd1)42 TEST(TransformIterator, VectorAdd1) {
43 auto add1 = [](const ValueHolder& h) { return h.value + 1; };
44 std::vector<ValueHolder> input({ 1, 7, 3, 8 });
45 std::vector<int> output;
46
47 using vector_titer = decltype(MakeTransformIterator(input.begin(), add1));
48 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_titer::iterator_category>);
49 static_assert(std::is_same_v<int, vector_titer::value_type>);
50 static_assert(std::is_same_v<vector_titer, vector_titer::pointer>);
51 static_assert(std::is_same_v<int, vector_titer::reference>);
52
53 using vector_ctiter = decltype(MakeTransformIterator(input.cbegin(), add1));
54 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_ctiter::iterator_category>);
55 static_assert(std::is_same_v<int, vector_ctiter::value_type>);
56 static_assert(std::is_same_v<vector_ctiter, vector_ctiter::pointer>);
57 static_assert(std::is_same_v<int, vector_ctiter::reference>);
58
59 using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), add1));
60 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_rtiter::iterator_category>);
61 static_assert(std::is_same_v<int, vector_rtiter::value_type>);
62 static_assert(std::is_same_v<vector_rtiter, vector_rtiter::pointer>);
63 static_assert(std::is_same_v<int, vector_rtiter::reference>);
64
65 using vector_crtiter = decltype(MakeTransformIterator(input.crbegin(), add1));
66 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_crtiter::iterator_category>);
67 static_assert(std::is_same_v<int, vector_crtiter::value_type>);
68 static_assert(std::is_same_v<vector_crtiter, vector_crtiter::pointer>);
69 static_assert(std::is_same_v<int, vector_crtiter::reference>);
70
71 std::copy(MakeTransformIterator(input.begin(), add1),
72 MakeTransformIterator(input.end(), add1),
73 std::back_inserter(output));
74 ASSERT_EQ(std::vector<int>({ 2, 8, 4, 9 }), output);
75 output.clear();
76
77 std::copy(MakeTransformIterator(input.cbegin(), add1),
78 MakeTransformIterator(input.cend(), add1),
79 std::back_inserter(output));
80 ASSERT_EQ(std::vector<int>({ 2, 8, 4, 9 }), output);
81 output.clear();
82
83 std::copy(MakeTransformIterator(input.rbegin(), add1),
84 MakeTransformIterator(input.rend(), add1),
85 std::back_inserter(output));
86 ASSERT_EQ(std::vector<int>({ 9, 4, 8, 2 }), output);
87 output.clear();
88
89 std::copy(MakeTransformIterator(input.crbegin(), add1),
90 MakeTransformIterator(input.crend(), add1),
91 std::back_inserter(output));
92 ASSERT_EQ(std::vector<int>({ 9, 4, 8, 2 }), output);
93 output.clear();
94
95 for (size_t i = 0; i != input.size(); ++i) {
96 ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.begin(), add1)[i]);
97 ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.cbegin(), add1)[i]);
98 ptrdiff_t index_from_rbegin = static_cast<ptrdiff_t>(input.size() - i - 1u);
99 ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.rbegin(), add1)[index_from_rbegin]);
100 ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.crbegin(), add1)[index_from_rbegin]);
101 ptrdiff_t index_from_end = -static_cast<ptrdiff_t>(input.size() - i);
102 ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.end(), add1)[index_from_end]);
103 ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.cend(), add1)[index_from_end]);
104 ptrdiff_t index_from_rend = -1 - static_cast<ptrdiff_t>(i);
105 ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.rend(), add1)[index_from_rend]);
106 ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.crend(), add1)[index_from_rend]);
107
108 ASSERT_EQ(MakeTransformIterator(input.begin(), add1) + i,
109 MakeTransformIterator(input.begin() + i, add1));
110 ASSERT_EQ(MakeTransformIterator(input.cbegin(), add1) + i,
111 MakeTransformIterator(input.cbegin() + i, add1));
112 ASSERT_EQ(MakeTransformIterator(input.rbegin(), add1) + i,
113 MakeTransformIterator(input.rbegin() + i, add1));
114 ASSERT_EQ(MakeTransformIterator(input.crbegin(), add1) + i,
115 MakeTransformIterator(input.crbegin() + i, add1));
116 ASSERT_EQ(MakeTransformIterator(input.end(), add1) - i,
117 MakeTransformIterator(input.end() - i, add1));
118 ASSERT_EQ(MakeTransformIterator(input.cend(), add1) - i,
119 MakeTransformIterator(input.cend() - i, add1));
120 ASSERT_EQ(MakeTransformIterator(input.rend(), add1) - i,
121 MakeTransformIterator(input.rend() - i, add1));
122 ASSERT_EQ(MakeTransformIterator(input.crend(), add1) - i,
123 MakeTransformIterator(input.crend() - i, add1));
124 }
125 ASSERT_EQ(input.end(),
126 (MakeTransformIterator(input.begin(), add1) + input.size()).base());
127 ASSERT_EQ(MakeTransformIterator(input.end(), add1) - MakeTransformIterator(input.begin(), add1),
128 static_cast<ptrdiff_t>(input.size()));
129
130 // Test iterator->const_iterator conversion and comparison.
131 auto it = MakeTransformIterator(input.begin(), add1);
132 decltype(MakeTransformIterator(input.cbegin(), add1)) cit = it;
133 static_assert(!std::is_same_v<decltype(it), decltype(cit)>, "Types must be different");
134 ASSERT_EQ(it, cit);
135 auto rit = MakeTransformIterator(input.rbegin(), add1);
136 decltype(MakeTransformIterator(input.crbegin(), add1)) crit(rit);
137 static_assert(!std::is_same_v<decltype(rit), decltype(crit)>, "Types must be different");
138 ASSERT_EQ(rit, crit);
139 }
140
TEST(TransformIterator,ListSub1)141 TEST(TransformIterator, ListSub1) {
142 auto sub1 = [](const ValueHolder& h) { return h.value - 1; };
143 std::list<ValueHolder> input({ 2, 3, 5, 7, 11 });
144 std::vector<int> output;
145
146 using list_titer = decltype(MakeTransformIterator(input.begin(), sub1));
147 static_assert(std::is_same_v<std::bidirectional_iterator_tag, list_titer::iterator_category>);
148 static_assert(std::is_same_v<int, list_titer::value_type>);
149 static_assert(std::is_same_v<list_titer, list_titer::pointer>);
150 static_assert(std::is_same_v<int, list_titer::reference>);
151
152 using list_ctiter = decltype(MakeTransformIterator(input.cbegin(), sub1));
153 static_assert(std::is_same_v<std::bidirectional_iterator_tag, list_ctiter::iterator_category>);
154 static_assert(std::is_same_v<int, list_ctiter::value_type>);
155 static_assert(std::is_same_v<list_ctiter, list_ctiter::pointer>);
156 static_assert(std::is_same_v<int, list_ctiter::reference>);
157
158 using list_rtiter = decltype(MakeTransformIterator(input.rbegin(), sub1));
159 static_assert(std::is_same_v<std::bidirectional_iterator_tag, list_rtiter::iterator_category>);
160 static_assert(std::is_same_v<int, list_rtiter::value_type>);
161 static_assert(std::is_same_v<list_rtiter, list_rtiter::pointer>);
162 static_assert(std::is_same_v<int, list_rtiter::reference>);
163
164 using list_crtiter = decltype(MakeTransformIterator(input.crbegin(), sub1));
165 static_assert(std::is_same_v<std::bidirectional_iterator_tag, list_crtiter::iterator_category>);
166 static_assert(std::is_same_v<int, list_crtiter::value_type>);
167 static_assert(std::is_same_v<list_crtiter, list_crtiter::pointer>);
168 static_assert(std::is_same_v<int, list_crtiter::reference>);
169
170 std::copy(MakeTransformIterator(input.begin(), sub1),
171 MakeTransformIterator(input.end(), sub1),
172 std::back_inserter(output));
173 ASSERT_EQ(std::vector<int>({ 1, 2, 4, 6, 10 }), output);
174 output.clear();
175
176 std::copy(MakeTransformIterator(input.cbegin(), sub1),
177 MakeTransformIterator(input.cend(), sub1),
178 std::back_inserter(output));
179 ASSERT_EQ(std::vector<int>({ 1, 2, 4, 6, 10 }), output);
180 output.clear();
181
182 std::copy(MakeTransformIterator(input.rbegin(), sub1),
183 MakeTransformIterator(input.rend(), sub1),
184 std::back_inserter(output));
185 ASSERT_EQ(std::vector<int>({ 10, 6, 4, 2, 1 }), output);
186 output.clear();
187
188 std::copy(MakeTransformIterator(input.crbegin(), sub1),
189 MakeTransformIterator(input.crend(), sub1),
190 std::back_inserter(output));
191 ASSERT_EQ(std::vector<int>({ 10, 6, 4, 2, 1 }), output);
192 output.clear();
193
194 // Test iterator->const_iterator conversion and comparison.
195 auto it = MakeTransformIterator(input.begin(), sub1);
196 decltype(MakeTransformIterator(input.cbegin(), sub1)) cit = it;
197 static_assert(!std::is_same_v<decltype(it), decltype(cit)>, "Types must be different");
198 ASSERT_EQ(it, cit);
199 }
200
TEST(TransformIterator,ForwardListSub1)201 TEST(TransformIterator, ForwardListSub1) {
202 auto mul3 = [](const ValueHolder& h) { return h.value * 3; };
203 std::forward_list<ValueHolder> input({ 1, 1, 2, 3, 5, 8 });
204 std::vector<int> output;
205
206 using flist_titer = decltype(MakeTransformIterator(input.begin(), mul3));
207 static_assert(std::is_same_v<std::forward_iterator_tag, flist_titer::iterator_category>);
208 static_assert(std::is_same_v<int, flist_titer::value_type>);
209 static_assert(std::is_same_v<flist_titer, flist_titer::pointer>);
210 static_assert(std::is_same_v<int, flist_titer::reference>);
211
212 using flist_ctiter = decltype(MakeTransformIterator(input.cbegin(), mul3));
213 static_assert(std::is_same_v<std::forward_iterator_tag, flist_ctiter::iterator_category>);
214 static_assert(std::is_same_v<int, flist_ctiter::value_type>);
215 static_assert(std::is_same_v<flist_ctiter, flist_ctiter::pointer>);
216 static_assert(std::is_same_v<int, flist_ctiter::reference>);
217
218 std::copy(MakeTransformIterator(input.begin(), mul3),
219 MakeTransformIterator(input.end(), mul3),
220 std::back_inserter(output));
221 ASSERT_EQ(std::vector<int>({ 3, 3, 6, 9, 15, 24 }), output);
222 output.clear();
223
224 std::copy(MakeTransformIterator(input.cbegin(), mul3),
225 MakeTransformIterator(input.cend(), mul3),
226 std::back_inserter(output));
227 ASSERT_EQ(std::vector<int>({ 3, 3, 6, 9, 15, 24 }), output);
228 output.clear();
229
230 // Test iterator->const_iterator conversion and comparison.
231 auto it = MakeTransformIterator(input.begin(), mul3);
232 decltype(MakeTransformIterator(input.cbegin(), mul3)) cit = it;
233 static_assert(!std::is_same_v<decltype(it), decltype(cit)>, "Types must be different");
234 ASSERT_EQ(it, cit);
235 }
236
TEST(TransformIterator,VectorConstReference)237 TEST(TransformIterator, VectorConstReference) {
238 auto ref = [](const ValueHolder& h) -> const int& { return h.value; };
239 std::vector<ValueHolder> input({ 7, 3, 1, 2, 4, 8 });
240 std::vector<int> output;
241
242 using vector_titer = decltype(MakeTransformIterator(input.begin(), ref));
243 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_titer::iterator_category>);
244 static_assert(std::is_same_v<int, vector_titer::value_type>);
245 static_assert(std::is_same_v<const int*, vector_titer::pointer>);
246 static_assert(std::is_same_v<const int&, vector_titer::reference>);
247
248 using vector_ctiter = decltype(MakeTransformIterator(input.cbegin(), ref));
249 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_ctiter::iterator_category>);
250 static_assert(std::is_same_v<int, vector_ctiter::value_type>);
251 static_assert(std::is_same_v<const int*, vector_ctiter::pointer>);
252 static_assert(std::is_same_v<const int&, vector_ctiter::reference>);
253
254 using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), ref));
255 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_rtiter::iterator_category>);
256 static_assert(std::is_same_v<int, vector_rtiter::value_type>);
257 static_assert(std::is_same_v<const int*, vector_rtiter::pointer>);
258 static_assert(std::is_same_v<const int&, vector_rtiter::reference>);
259
260 using vector_crtiter = decltype(MakeTransformIterator(input.crbegin(), ref));
261 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_crtiter::iterator_category>);
262 static_assert(std::is_same_v<int, vector_crtiter::value_type>);
263 static_assert(std::is_same_v<const int*, vector_crtiter::pointer>);
264 static_assert(std::is_same_v<const int&, vector_crtiter::reference>);
265
266 std::copy(MakeTransformIterator(input.begin(), ref),
267 MakeTransformIterator(input.end(), ref),
268 std::back_inserter(output));
269 ASSERT_EQ(std::vector<int>({ 7, 3, 1, 2, 4, 8 }), output);
270 output.clear();
271
272 std::copy(MakeTransformIterator(input.cbegin(), ref),
273 MakeTransformIterator(input.cend(), ref),
274 std::back_inserter(output));
275 ASSERT_EQ(std::vector<int>({ 7, 3, 1, 2, 4, 8 }), output);
276 output.clear();
277
278 std::copy(MakeTransformIterator(input.rbegin(), ref),
279 MakeTransformIterator(input.rend(), ref),
280 std::back_inserter(output));
281 ASSERT_EQ(std::vector<int>({ 8, 4, 2, 1, 3, 7 }), output);
282 output.clear();
283
284 std::copy(MakeTransformIterator(input.crbegin(), ref),
285 MakeTransformIterator(input.crend(), ref),
286 std::back_inserter(output));
287 ASSERT_EQ(std::vector<int>({ 8, 4, 2, 1, 3, 7 }), output);
288 output.clear();
289
290 for (size_t i = 0; i != input.size(); ++i) {
291 ASSERT_EQ(input[i].value, MakeTransformIterator(input.begin(), ref)[i]);
292 ASSERT_EQ(input[i].value, MakeTransformIterator(input.cbegin(), ref)[i]);
293 ptrdiff_t index_from_rbegin = static_cast<ptrdiff_t>(input.size() - i - 1u);
294 ASSERT_EQ(input[i].value, MakeTransformIterator(input.rbegin(), ref)[index_from_rbegin]);
295 ASSERT_EQ(input[i].value, MakeTransformIterator(input.crbegin(), ref)[index_from_rbegin]);
296 ptrdiff_t index_from_end = -static_cast<ptrdiff_t>(input.size() - i);
297 ASSERT_EQ(input[i].value, MakeTransformIterator(input.end(), ref)[index_from_end]);
298 ASSERT_EQ(input[i].value, MakeTransformIterator(input.cend(), ref)[index_from_end]);
299 ptrdiff_t index_from_rend = -1 - static_cast<ptrdiff_t>(i);
300 ASSERT_EQ(input[i].value, MakeTransformIterator(input.rend(), ref)[index_from_rend]);
301 ASSERT_EQ(input[i].value, MakeTransformIterator(input.crend(), ref)[index_from_rend]);
302
303 ASSERT_EQ(MakeTransformIterator(input.begin(), ref) + i,
304 MakeTransformIterator(input.begin() + i, ref));
305 ASSERT_EQ(MakeTransformIterator(input.cbegin(), ref) + i,
306 MakeTransformIterator(input.cbegin() + i, ref));
307 ASSERT_EQ(MakeTransformIterator(input.rbegin(), ref) + i,
308 MakeTransformIterator(input.rbegin() + i, ref));
309 ASSERT_EQ(MakeTransformIterator(input.crbegin(), ref) + i,
310 MakeTransformIterator(input.crbegin() + i, ref));
311 ASSERT_EQ(MakeTransformIterator(input.end(), ref) - i,
312 MakeTransformIterator(input.end() - i, ref));
313 ASSERT_EQ(MakeTransformIterator(input.cend(), ref) - i,
314 MakeTransformIterator(input.cend() - i, ref));
315 ASSERT_EQ(MakeTransformIterator(input.rend(), ref) - i,
316 MakeTransformIterator(input.rend() - i, ref));
317 ASSERT_EQ(MakeTransformIterator(input.crend(), ref) - i,
318 MakeTransformIterator(input.crend() - i, ref));
319 }
320 ASSERT_EQ(input.end(),
321 (MakeTransformIterator(input.begin(), ref) + input.size()).base());
322 ASSERT_EQ(MakeTransformIterator(input.end(), ref) - MakeTransformIterator(input.begin(), ref),
323 static_cast<ptrdiff_t>(input.size()));
324 }
325
TEST(TransformIterator,VectorNonConstReference)326 TEST(TransformIterator, VectorNonConstReference) {
327 auto ref = [](ValueHolder& h) -> int& { return h.value; };
328 std::vector<ValueHolder> input({ 7, 3, 1, 2, 4, 8 });
329 std::vector<int> output;
330
331 using vector_titer = decltype(MakeTransformIterator(input.begin(), ref));
332 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_titer::iterator_category>);
333 static_assert(std::is_same_v<int, vector_titer::value_type>);
334 static_assert(std::is_same_v<int*, vector_titer::pointer>);
335 static_assert(std::is_same_v<int&, vector_titer::reference>);
336
337 using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), ref));
338 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_rtiter::iterator_category>);
339 static_assert(std::is_same_v<int, vector_rtiter::value_type>);
340 static_assert(std::is_same_v<int*, vector_rtiter::pointer>);
341 static_assert(std::is_same_v<int&, vector_rtiter::reference>);
342
343 std::copy(MakeTransformIterator(input.begin(), ref),
344 MakeTransformIterator(input.end(), ref),
345 std::back_inserter(output));
346 ASSERT_EQ(std::vector<int>({ 7, 3, 1, 2, 4, 8 }), output);
347 output.clear();
348
349 std::copy(MakeTransformIterator(input.rbegin(), ref),
350 MakeTransformIterator(input.rend(), ref),
351 std::back_inserter(output));
352 ASSERT_EQ(std::vector<int>({ 8, 4, 2, 1, 3, 7 }), output);
353 output.clear();
354
355 for (size_t i = 0; i != input.size(); ++i) {
356 ASSERT_EQ(input[i].value, MakeTransformIterator(input.begin(), ref)[i]);
357 ptrdiff_t index_from_rbegin = static_cast<ptrdiff_t>(input.size() - i - 1u);
358 ASSERT_EQ(input[i].value, MakeTransformIterator(input.rbegin(), ref)[index_from_rbegin]);
359 ptrdiff_t index_from_end = -static_cast<ptrdiff_t>(input.size() - i);
360 ASSERT_EQ(input[i].value, MakeTransformIterator(input.end(), ref)[index_from_end]);
361 ptrdiff_t index_from_rend = -1 - static_cast<ptrdiff_t>(i);
362 ASSERT_EQ(input[i].value, MakeTransformIterator(input.rend(), ref)[index_from_rend]);
363
364 ASSERT_EQ(MakeTransformIterator(input.begin(), ref) + i,
365 MakeTransformIterator(input.begin() + i, ref));
366 ASSERT_EQ(MakeTransformIterator(input.rbegin(), ref) + i,
367 MakeTransformIterator(input.rbegin() + i, ref));
368 ASSERT_EQ(MakeTransformIterator(input.end(), ref) - i,
369 MakeTransformIterator(input.end() - i, ref));
370 ASSERT_EQ(MakeTransformIterator(input.rend(), ref) - i,
371 MakeTransformIterator(input.rend() - i, ref));
372 }
373 ASSERT_EQ(input.end(),
374 (MakeTransformIterator(input.begin(), ref) + input.size()).base());
375 ASSERT_EQ(MakeTransformIterator(input.end(), ref) - MakeTransformIterator(input.begin(), ref),
376 static_cast<ptrdiff_t>(input.size()));
377
378 // Test writing through the transform iterator.
379 std::list<int> transform_input({ 1, -1, 2, -2, 3, -3 });
380 std::vector<ValueHolder> transformed(transform_input.size(), 0);
381 std::transform(transform_input.begin(),
382 transform_input.end(),
383 MakeTransformIterator(transformed.begin(), ref),
384 [](int v) { return -2 * v; });
385 ASSERT_EQ(std::vector<ValueHolder>({ -2, 2, -4, 4, -6, 6 }), transformed);
386 }
387
TEST(TransformIterator,VectorConstAndNonConstReference)388 TEST(TransformIterator, VectorConstAndNonConstReference) {
389 struct Ref {
390 int& operator()(ValueHolder& h) const { return h.value; }
391 const int& operator()(const ValueHolder& h) const { return h.value; }
392 };
393 Ref ref;
394 std::vector<ValueHolder> input({ 7, 3, 1, 2, 4, 8 });
395 std::vector<int> output;
396
397 using vector_titer = decltype(MakeTransformIterator(input.begin(), ref));
398 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_titer::iterator_category>);
399 static_assert(std::is_same_v<int, vector_titer::value_type>);
400 static_assert(std::is_same_v<int*, vector_titer::pointer>);
401 static_assert(std::is_same_v<int&, vector_titer::reference>);
402
403 using vector_ctiter = decltype(MakeTransformIterator(input.cbegin(), ref));
404 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_ctiter::iterator_category>);
405 static_assert(std::is_same_v<int, vector_ctiter::value_type>);
406 static_assert(std::is_same_v<const int*, vector_ctiter::pointer>);
407 static_assert(std::is_same_v<const int&, vector_ctiter::reference>);
408
409 using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), ref));
410 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_rtiter::iterator_category>);
411 static_assert(std::is_same_v<int, vector_rtiter::value_type>);
412 static_assert(std::is_same_v<int*, vector_rtiter::pointer>);
413 static_assert(std::is_same_v<int&, vector_rtiter::reference>);
414
415 using vector_crtiter = decltype(MakeTransformIterator(input.crbegin(), ref));
416 static_assert(std::is_same_v<std::random_access_iterator_tag, vector_crtiter::iterator_category>);
417 static_assert(std::is_same_v<int, vector_crtiter::value_type>);
418 static_assert(std::is_same_v<const int*, vector_crtiter::pointer>);
419 static_assert(std::is_same_v<const int&, vector_crtiter::reference>);
420
421 std::copy(MakeTransformIterator(input.begin(), ref),
422 MakeTransformIterator(input.end(), ref),
423 std::back_inserter(output));
424 ASSERT_EQ(std::vector<int>({ 7, 3, 1, 2, 4, 8 }), output);
425 output.clear();
426
427 std::copy(MakeTransformIterator(input.cbegin(), ref),
428 MakeTransformIterator(input.cend(), ref),
429 std::back_inserter(output));
430 ASSERT_EQ(std::vector<int>({ 7, 3, 1, 2, 4, 8 }), output);
431 output.clear();
432
433 std::copy(MakeTransformIterator(input.rbegin(), ref),
434 MakeTransformIterator(input.rend(), ref),
435 std::back_inserter(output));
436 ASSERT_EQ(std::vector<int>({ 8, 4, 2, 1, 3, 7 }), output);
437 output.clear();
438
439 std::copy(MakeTransformIterator(input.crbegin(), ref),
440 MakeTransformIterator(input.crend(), ref),
441 std::back_inserter(output));
442 ASSERT_EQ(std::vector<int>({ 8, 4, 2, 1, 3, 7 }), output);
443 output.clear();
444
445 for (size_t i = 0; i != input.size(); ++i) {
446 ASSERT_EQ(input[i].value, MakeTransformIterator(input.begin(), ref)[i]);
447 ASSERT_EQ(input[i].value, MakeTransformIterator(input.cbegin(), ref)[i]);
448 ptrdiff_t index_from_rbegin = static_cast<ptrdiff_t>(input.size() - i - 1u);
449 ASSERT_EQ(input[i].value, MakeTransformIterator(input.rbegin(), ref)[index_from_rbegin]);
450 ASSERT_EQ(input[i].value, MakeTransformIterator(input.crbegin(), ref)[index_from_rbegin]);
451 ptrdiff_t index_from_end = -static_cast<ptrdiff_t>(input.size() - i);
452 ASSERT_EQ(input[i].value, MakeTransformIterator(input.end(), ref)[index_from_end]);
453 ASSERT_EQ(input[i].value, MakeTransformIterator(input.cend(), ref)[index_from_end]);
454 ptrdiff_t index_from_rend = -1 - static_cast<ptrdiff_t>(i);
455 ASSERT_EQ(input[i].value, MakeTransformIterator(input.rend(), ref)[index_from_rend]);
456 ASSERT_EQ(input[i].value, MakeTransformIterator(input.crend(), ref)[index_from_rend]);
457
458 ASSERT_EQ(MakeTransformIterator(input.begin(), ref) + i,
459 MakeTransformIterator(input.begin() + i, ref));
460 ASSERT_EQ(MakeTransformIterator(input.cbegin(), ref) + i,
461 MakeTransformIterator(input.cbegin() + i, ref));
462 ASSERT_EQ(MakeTransformIterator(input.rbegin(), ref) + i,
463 MakeTransformIterator(input.rbegin() + i, ref));
464 ASSERT_EQ(MakeTransformIterator(input.crbegin(), ref) + i,
465 MakeTransformIterator(input.crbegin() + i, ref));
466 ASSERT_EQ(MakeTransformIterator(input.end(), ref) - i,
467 MakeTransformIterator(input.end() - i, ref));
468 ASSERT_EQ(MakeTransformIterator(input.cend(), ref) - i,
469 MakeTransformIterator(input.cend() - i, ref));
470 ASSERT_EQ(MakeTransformIterator(input.rend(), ref) - i,
471 MakeTransformIterator(input.rend() - i, ref));
472 ASSERT_EQ(MakeTransformIterator(input.crend(), ref) - i,
473 MakeTransformIterator(input.crend() - i, ref));
474 }
475 ASSERT_EQ(input.end(),
476 (MakeTransformIterator(input.begin(), ref) + input.size()).base());
477 ASSERT_EQ(MakeTransformIterator(input.end(), ref) - MakeTransformIterator(input.begin(), ref),
478 static_cast<ptrdiff_t>(input.size()));
479
480 // Test iterator->const_iterator conversion and comparison.
481 auto it = MakeTransformIterator(input.begin(), ref);
482 decltype(MakeTransformIterator(input.cbegin(), ref)) cit = it;
483 static_assert(!std::is_same_v<decltype(it), decltype(cit)>, "Types must be different");
484 ASSERT_EQ(it, cit);
485 auto rit = MakeTransformIterator(input.rbegin(), ref);
486 decltype(MakeTransformIterator(input.crbegin(), ref)) crit(rit);
487 static_assert(!std::is_same_v<decltype(rit), decltype(crit)>, "Types must be different");
488 ASSERT_EQ(rit, crit);
489
490 // Test writing through the transform iterator.
491 std::list<int> transform_input({ 42, 73, 11, 17 });
492 std::vector<ValueHolder> transformed(transform_input.size(), 0);
493 std::transform(transform_input.begin(),
494 transform_input.end(),
495 MakeTransformIterator(transformed.begin(), ref),
496 [](int v) { return -v; });
497 ASSERT_EQ(std::vector<ValueHolder>({ -42, -73, -11, -17 }), transformed);
498 }
499
TEST(TransformIterator,TransformRange)500 TEST(TransformIterator, TransformRange) {
501 auto ref = [](ValueHolder& h) -> int& { return h.value; };
502 std::vector<ValueHolder> data({ 1, 0, 1, 3, 1, 0 });
503
504 for (int& v : MakeTransformRange(data, ref)) {
505 v += 11;
506 }
507 ASSERT_EQ(std::vector<ValueHolder>({ 12, 11, 12, 14, 12, 11 }), data);
508 }
509
510 } // namespace art
511