1 //===------ MappedIteratorTest.cpp - Unit tests for mapped_iterator -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/ADT/STLExtras.h"
10 #include "gtest/gtest.h"
11 
12 using namespace llvm;
13 
14 namespace {
15 
TEST(MappedIteratorTest,ApplyFunctionOnDereference)16 TEST(MappedIteratorTest, ApplyFunctionOnDereference) {
17   std::vector<int> V({0});
18 
19   auto I = map_iterator(V.begin(), [](int X) { return X + 1; });
20 
21   EXPECT_EQ(*I, 1) << "should have applied function in dereference";
22 }
23 
TEST(MappedIteratorTest,ApplyFunctionOnArrow)24 TEST(MappedIteratorTest, ApplyFunctionOnArrow) {
25   struct S {
26     int Z = 0;
27   };
28 
29   std::vector<int> V({0});
30   S Y;
31   S* P = &Y;
32 
33   auto I = map_iterator(V.begin(), [&](int X) -> S& { return *(P + X); });
34 
35   I->Z = 42;
36 
37   EXPECT_EQ(Y.Z, 42) << "should have applied function during arrow";
38 }
39 
TEST(MappedIteratorTest,FunctionPreservesReferences)40 TEST(MappedIteratorTest, FunctionPreservesReferences) {
41   std::vector<int> V({1});
42   std::map<int, int> M({ {1, 1} });
43 
44   auto I = map_iterator(V.begin(), [&](int X) -> int& { return M[X]; });
45   *I = 42;
46 
47   EXPECT_EQ(M[1], 42) << "assignment should have modified M";
48 }
49 
TEST(MappedIteratorTest,CustomIteratorApplyFunctionOnDereference)50 TEST(MappedIteratorTest, CustomIteratorApplyFunctionOnDereference) {
51   struct CustomMapIterator
52       : public llvm::mapped_iterator_base<CustomMapIterator,
53                                           std::vector<int>::iterator, int> {
54     using BaseT::BaseT;
55 
56     /// Map the element to the iterator result type.
57     int mapElement(int X) const { return X + 1; }
58   };
59 
60   std::vector<int> V({0});
61 
62   CustomMapIterator I(V.begin());
63 
64   EXPECT_EQ(*I, 1) << "should have applied function in dereference";
65 }
66 
TEST(MappedIteratorTest,CustomIteratorApplyFunctionOnArrow)67 TEST(MappedIteratorTest, CustomIteratorApplyFunctionOnArrow) {
68   struct S {
69     int Z = 0;
70   };
71   struct CustomMapIterator
72       : public llvm::mapped_iterator_base<CustomMapIterator,
73                                           std::vector<int>::iterator, S &> {
74     CustomMapIterator(std::vector<int>::iterator it, S *P) : BaseT(it), P(P) {}
75 
76     /// Map the element to the iterator result type.
77     S &mapElement(int X) const { return *(P + X); }
78 
79     S *P;
80   };
81 
82   std::vector<int> V({0});
83   S Y;
84 
85   CustomMapIterator I(V.begin(), &Y);
86 
87   I->Z = 42;
88 
89   EXPECT_EQ(Y.Z, 42) << "should have applied function during arrow";
90 }
91 
TEST(MappedIteratorTest,CustomIteratorFunctionPreservesReferences)92 TEST(MappedIteratorTest, CustomIteratorFunctionPreservesReferences) {
93   struct CustomMapIterator
94       : public llvm::mapped_iterator_base<CustomMapIterator,
95                                           std::vector<int>::iterator, int &> {
96     CustomMapIterator(std::vector<int>::iterator it, std::map<int, int> &M)
97         : BaseT(it), M(M) {}
98 
99     /// Map the element to the iterator result type.
100     int &mapElement(int X) const { return M[X]; }
101 
102     std::map<int, int> &M;
103   };
104   std::vector<int> V({1});
105   std::map<int, int> M({{1, 1}});
106 
107   auto I = CustomMapIterator(V.begin(), M);
108   *I = 42;
109 
110   EXPECT_EQ(M[1], 42) << "assignment should have modified M";
111 }
112 
113 } // anonymous namespace
114