Home | History | Annotate | Download | only in base
      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.
     33   ValueHolder(int v) : value(v) { }  // NOLINT
     34   int value;
     35 };
     36 
     37 bool operator==(const ValueHolder& lhs, const ValueHolder& rhs) {
     38   return lhs.value == rhs.value;
     39 }
     40 
     41 }  // anonymous namespace
     42 
     43 TEST(TransformIterator, VectorAdd1) {
     44   auto add1 = [](const ValueHolder& h) { return h.value + 1; };
     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 
    146 TEST(TransformIterator, ListSub1) {
    147   auto sub1 = [](const ValueHolder& h) { return h.value - 1; };
    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 
    210 TEST(TransformIterator, ForwardListSub1) {
    211   auto mul3 = [](const ValueHolder& h) { return h.value * 3; };
    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 
    248 TEST(TransformIterator, VectorConstReference) {
    249   auto ref = [](const ValueHolder& h) -> const int& { return h.value; };
    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 
    341 TEST(TransformIterator, VectorNonConstReference) {
    342   auto ref = [](ValueHolder& h) -> int& { return h.value; };
    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 
    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 
    521 TEST(TransformIterator, TransformRange) {
    522   auto ref = [](ValueHolder& h) -> int& { return h.value; };
    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