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