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