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