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