@@ -39,51 +39,152 @@ TEST(STLExtrasTest, Rank) {
3939 EXPECT_EQ (4 , f (rank<6 >()));
4040}
4141
42- TEST (STLExtrasTest, Enumerate) {
42+ TEST (STLExtrasTest, EnumerateLValue) {
43+ // Test that a simple LValue can be enumerated and gives correct results with
44+ // multiple types, including the empty container.
4345 std::vector<char > foo = {' a' , ' b' , ' c' };
44-
45- std::vector<std::pair<std::size_t , char >> results;
46+ std::vector<std::pair<std::size_t , char >> CharResults;
4647
4748 for (auto X : llvm::enumerate (foo)) {
48- results. push_back ( std::make_pair ( X.Index , X.Value ) );
49+ CharResults. emplace_back ( X.Index , X.Value );
4950 }
50- ASSERT_EQ (3u , results.size ());
51- EXPECT_EQ (0u , results[0 ].first );
52- EXPECT_EQ (' a' , results[0 ].second );
53- EXPECT_EQ (1u , results[1 ].first );
54- EXPECT_EQ (' b' , results[1 ].second );
55- EXPECT_EQ (2u , results[2 ].first );
56- EXPECT_EQ (' c' , results[2 ].second );
57-
58- results.clear ();
59- const std::vector<int > bar = {' 1' , ' 2' , ' 3' };
51+ ASSERT_EQ (3u , CharResults.size ());
52+ EXPECT_EQ (std::make_pair (0u , ' a' ), CharResults[0 ]);
53+ EXPECT_EQ (std::make_pair (1u , ' b' ), CharResults[1 ]);
54+ EXPECT_EQ (std::make_pair (2u , ' c' ), CharResults[2 ]);
55+
56+ // Test a const range of a different type.
57+ std::vector<std::pair<std::size_t , int >> IntResults;
58+ const std::vector<int > bar = {1 , 2 , 3 };
6059 for (auto X : llvm::enumerate (bar)) {
61- results. push_back ( std::make_pair ( X.Index , X.Value ) );
60+ IntResults. emplace_back ( X.Index , X.Value );
6261 }
63- EXPECT_EQ (0u , results[0 ].first );
64- EXPECT_EQ (' 1' , results[0 ].second );
65- EXPECT_EQ (1u , results[1 ].first );
66- EXPECT_EQ (' 2' , results[1 ].second );
67- EXPECT_EQ (2u , results[2 ].first );
68- EXPECT_EQ (' 3' , results[2 ].second );
69-
70- results.clear ();
62+ ASSERT_EQ (3u , IntResults.size ());
63+ EXPECT_EQ (std::make_pair (0u , 1 ), IntResults[0 ]);
64+ EXPECT_EQ (std::make_pair (1u , 2 ), IntResults[1 ]);
65+ EXPECT_EQ (std::make_pair (2u , 3 ), IntResults[2 ]);
66+
67+ // Test an empty range.
68+ IntResults.clear ();
7169 const std::vector<int > baz;
7270 for (auto X : llvm::enumerate (baz)) {
73- results. push_back ( std::make_pair ( X.Index , X.Value ) );
71+ IntResults. emplace_back ( X.Index , X.Value );
7472 }
75- EXPECT_TRUE (baz .empty ());
73+ EXPECT_TRUE (IntResults .empty ());
7674}
7775
78- TEST (STLExtrasTest, EnumerateModify) {
76+ TEST (STLExtrasTest, EnumerateModifyLValue) {
77+ // Test that you can modify the underlying entries of an lvalue range through
78+ // the enumeration iterator.
7979 std::vector<char > foo = {' a' , ' b' , ' c' };
8080
8181 for (auto X : llvm::enumerate (foo)) {
8282 ++X.Value ;
8383 }
84-
8584 EXPECT_EQ (' b' , foo[0 ]);
8685 EXPECT_EQ (' c' , foo[1 ]);
8786 EXPECT_EQ (' d' , foo[2 ]);
8887}
88+
89+ TEST (STLExtrasTest, EnumerateRValueRef) {
90+ // Test that an rvalue can be enumerated.
91+ std::vector<std::pair<std::size_t , int >> Results;
92+
93+ auto Enumerator = llvm::enumerate (std::vector<int >{1 , 2 , 3 });
94+
95+ for (auto X : llvm::enumerate (std::vector<int >{1 , 2 , 3 })) {
96+ Results.emplace_back (X.Index , X.Value );
97+ }
98+
99+ ASSERT_EQ (3u , Results.size ());
100+ EXPECT_EQ (std::make_pair (0u , 1 ), Results[0 ]);
101+ EXPECT_EQ (std::make_pair (1u , 2 ), Results[1 ]);
102+ EXPECT_EQ (std::make_pair (2u , 3 ), Results[2 ]);
103+ }
104+
105+ TEST (STLExtrasTest, EnumerateModifyRValue) {
106+ // Test that when enumerating an rvalue, modification still works (even if
107+ // this isn't terribly useful, it at least shows that we haven't snuck an
108+ // extra const in there somewhere.
109+ std::vector<std::pair<std::size_t , char >> Results;
110+
111+ for (auto X : llvm::enumerate (std::vector<char >{' 1' , ' 2' , ' 3' })) {
112+ ++X.Value ;
113+ Results.emplace_back (X.Index , X.Value );
114+ }
115+
116+ ASSERT_EQ (3u , Results.size ());
117+ EXPECT_EQ (std::make_pair (0u , ' 2' ), Results[0 ]);
118+ EXPECT_EQ (std::make_pair (1u , ' 3' ), Results[1 ]);
119+ EXPECT_EQ (std::make_pair (2u , ' 4' ), Results[2 ]);
120+ }
121+
122+ template <bool B> struct CanMove {};
123+ template <> struct CanMove <false > {
124+ CanMove (CanMove &&) = delete ;
125+
126+ CanMove () = default ;
127+ CanMove (const CanMove &) = default ;
128+ };
129+
130+ template <bool B> struct CanCopy {};
131+ template <> struct CanCopy <false > {
132+ CanCopy (const CanCopy &) = delete ;
133+
134+ CanCopy () = default ;
135+ CanCopy (CanCopy &&) = default ;
136+ };
137+
138+ template <bool Moveable, bool Copyable>
139+ struct Range : CanMove<Moveable>, CanCopy<Copyable> {
140+ explicit Range (int &C, int &M, int &D) : C(C), M(M), D(D) {}
141+ Range (const Range &R) : CanCopy<Copyable>(R), C(R.C), M(R.M), D(R.D) { ++C; }
142+ Range (Range &&R) : CanMove<Moveable>(std::move(R)), C(R.C), M(R.M), D(R.D) {
143+ ++M;
144+ }
145+ ~Range () { ++D; }
146+
147+ int &C;
148+ int &M;
149+ int &D;
150+
151+ int *begin () { return nullptr ; }
152+ int *end () { return nullptr ; }
153+ };
154+
155+ TEST (STLExtrasTest, EnumerateLifetimeSemantics) {
156+ // Test that when enumerating lvalues and rvalues, there are no surprise
157+ // copies or moves.
158+
159+ // With an rvalue, it should not be destroyed until the end of the scope.
160+ int Copies = 0 ;
161+ int Moves = 0 ;
162+ int Destructors = 0 ;
163+ {
164+ auto E1 = enumerate(Range<true , false >(Copies, Moves, Destructors));
165+ // Doesn't compile. rvalue ranges must be moveable.
166+ // auto E2 = enumerate(Range<false, true>(Copies, Moves, Destructors));
167+ EXPECT_EQ (0 , Copies);
168+ EXPECT_EQ (1 , Moves);
169+ EXPECT_EQ (1 , Destructors);
170+ }
171+ EXPECT_EQ (0 , Copies);
172+ EXPECT_EQ (1 , Moves);
173+ EXPECT_EQ (2 , Destructors);
174+
175+ Copies = Moves = Destructors = 0 ;
176+ // With an lvalue, it should not be destroyed even after the end of the scope.
177+ // lvalue ranges need be neither copyable nor moveable.
178+ Range<false , false > R (Copies, Moves, Destructors);
179+ {
180+ auto Enumerator = enumerate(R);
181+ (void )Enumerator;
182+ EXPECT_EQ (0 , Copies);
183+ EXPECT_EQ (0 , Moves);
184+ EXPECT_EQ (0 , Destructors);
185+ }
186+ EXPECT_EQ (0 , Copies);
187+ EXPECT_EQ (0 , Moves);
188+ EXPECT_EQ (0 , Destructors);
189+ }
89190}
0 commit comments