1 //===- IteratorTest.cpp - Unit tests for iterator utilities ---------------===//
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/ilist.h"
10 #include "llvm/ADT/iterator.h"
11 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "gtest/gtest.h"
15
16 using namespace llvm;
17
18 namespace {
19
20 template <int> struct Shadow;
21
22 struct WeirdIter : std::iterator<std::input_iterator_tag, Shadow<0>, Shadow<1>,
23 Shadow<2>, Shadow<3>> {};
24
25 struct AdaptedIter : iterator_adaptor_base<AdaptedIter, WeirdIter> {};
26
27 // Test that iterator_adaptor_base forwards typedefs, if value_type is
28 // unchanged.
29 static_assert(std::is_same<typename AdaptedIter::value_type, Shadow<0>>::value,
30 "");
31 static_assert(
32 std::is_same<typename AdaptedIter::difference_type, Shadow<1>>::value, "");
33 static_assert(std::is_same<typename AdaptedIter::pointer, Shadow<2>>::value,
34 "");
35 static_assert(std::is_same<typename AdaptedIter::reference, Shadow<3>>::value,
36 "");
37
38 // Ensure that pointe{e,r}_iterator adaptors correctly forward the category of
39 // the underlying iterator.
40
41 using RandomAccessIter = SmallVectorImpl<int*>::iterator;
42 using BidiIter = ilist<int*>::iterator;
43
44 template<class T>
45 using pointee_iterator_defaulted = pointee_iterator<T>;
46 template<class T>
47 using pointer_iterator_defaulted = pointer_iterator<T>;
48
49 // Ensures that an iterator and its adaptation have the same iterator_category.
50 template<template<typename> class A, typename It>
51 using IsAdaptedIterCategorySame =
52 std::is_same<typename std::iterator_traits<It>::iterator_category,
53 typename std::iterator_traits<A<It>>::iterator_category>;
54
55 // Check that dereferencing works correctly adapting pointers and proxies.
56 template <class T>
57 struct PointerWrapper : public iterator_adaptor_base<PointerWrapper<T>, T *> {
PointerWrapper__anon200c40ce0111::PointerWrapper58 PointerWrapper(T *I) : PointerWrapper::iterator_adaptor_base(I) {}
59 };
60 struct IntProxy {
61 int &I;
IntProxy__anon200c40ce0111::IntProxy62 IntProxy(int &I) : I(I) {}
operator =__anon200c40ce0111::IntProxy63 void operator=(int NewValue) { I = NewValue; }
64 };
65 struct ConstIntProxy {
66 const int &I;
ConstIntProxy__anon200c40ce0111::ConstIntProxy67 ConstIntProxy(const int &I) : I(I) {}
68 };
69 template <class T, class ProxyT>
70 struct PointerProxyWrapper
71 : public iterator_adaptor_base<PointerProxyWrapper<T, ProxyT>, T *,
72 std::random_access_iterator_tag, T,
73 ptrdiff_t, T *, ProxyT> {
PointerProxyWrapper__anon200c40ce0111::PointerProxyWrapper74 PointerProxyWrapper(T *I) : PointerProxyWrapper::iterator_adaptor_base(I) {}
75 };
76 using IntIterator = PointerWrapper<int>;
77 using ConstIntIterator = PointerWrapper<const int>;
78 using IntProxyIterator = PointerProxyWrapper<int, IntProxy>;
79 using ConstIntProxyIterator = PointerProxyWrapper<const int, ConstIntProxy>;
80
81 // There should only be a single (const-qualified) operator*, operator->, and
82 // operator[]. This test confirms that there isn't a non-const overload. Rather
83 // than adding those, users should double-check that T, PointerT, and ReferenceT
84 // have the right constness, and/or make fields mutable.
85 static_assert(&IntIterator::operator* == &IntIterator::operator*, "");
86 static_assert(&IntIterator::operator-> == &IntIterator::operator->, "");
87 static_assert(&IntIterator::operator[] == &IntIterator::operator[], "");
88
89 template <class T,
90 std::enable_if_t<std::is_assignable<T, int>::value, bool> = false>
canAssignFromInt(T &&)91 constexpr bool canAssignFromInt(T &&) {
92 return true;
93 }
94 template <class T,
95 std::enable_if_t<!std::is_assignable<T, int>::value, bool> = false>
canAssignFromInt(T &&)96 constexpr bool canAssignFromInt(T &&) {
97 return false;
98 }
99
TEST(IteratorAdaptorTest,Dereference)100 TEST(IteratorAdaptorTest, Dereference) {
101 int Number = 1;
102
103 // Construct some iterators and check whether they can be assigned to.
104 IntIterator I(&Number);
105 const IntIterator IC(&Number);
106 ConstIntIterator CI(&Number);
107 const ConstIntIterator CIC(&Number);
108 EXPECT_EQ(true, canAssignFromInt(*I)); // int *
109 EXPECT_EQ(true, canAssignFromInt(*IC)); // int *const
110 EXPECT_EQ(false, canAssignFromInt(*CI)); // const int *
111 EXPECT_EQ(false, canAssignFromInt(*CIC)); // const int *const
112
113 // Prove that dereference and assignment work.
114 EXPECT_EQ(1, *I);
115 EXPECT_EQ(1, *IC);
116 EXPECT_EQ(1, *CI);
117 EXPECT_EQ(1, *CIC);
118 *I = 2;
119 EXPECT_EQ(2, Number);
120 *IC = 3;
121 EXPECT_EQ(3, Number);
122
123 // Construct some proxy iterators and check whether they can be assigned to.
124 IntProxyIterator P(&Number);
125 const IntProxyIterator PC(&Number);
126 ConstIntProxyIterator CP(&Number);
127 const ConstIntProxyIterator CPC(&Number);
128 EXPECT_EQ(true, canAssignFromInt(*P)); // int *
129 EXPECT_EQ(true, canAssignFromInt(*PC)); // int *const
130 EXPECT_EQ(false, canAssignFromInt(*CP)); // const int *
131 EXPECT_EQ(false, canAssignFromInt(*CPC)); // const int *const
132
133 // Prove that dereference and assignment work.
134 EXPECT_EQ(3, (*P).I);
135 EXPECT_EQ(3, (*PC).I);
136 EXPECT_EQ(3, (*CP).I);
137 EXPECT_EQ(3, (*CPC).I);
138 *P = 4;
139 EXPECT_EQ(4, Number);
140 *PC = 5;
141 EXPECT_EQ(5, Number);
142 }
143
144 // pointeE_iterator
145 static_assert(IsAdaptedIterCategorySame<pointee_iterator_defaulted,
146 RandomAccessIter>::value, "");
147 static_assert(IsAdaptedIterCategorySame<pointee_iterator_defaulted,
148 BidiIter>::value, "");
149 // pointeR_iterator
150 static_assert(IsAdaptedIterCategorySame<pointer_iterator_defaulted,
151 RandomAccessIter>::value, "");
152 static_assert(IsAdaptedIterCategorySame<pointer_iterator_defaulted,
153 BidiIter>::value, "");
154
TEST(PointeeIteratorTest,Basic)155 TEST(PointeeIteratorTest, Basic) {
156 int arr[4] = {1, 2, 3, 4};
157 SmallVector<int *, 4> V;
158 V.push_back(&arr[0]);
159 V.push_back(&arr[1]);
160 V.push_back(&arr[2]);
161 V.push_back(&arr[3]);
162
163 typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator>
164 test_iterator;
165
166 test_iterator Begin, End;
167 Begin = V.begin();
168 End = test_iterator(V.end());
169
170 test_iterator I = Begin;
171 for (int i = 0; i < 4; ++i) {
172 EXPECT_EQ(*V[i], *I);
173
174 EXPECT_EQ(I, Begin + i);
175 EXPECT_EQ(I, std::next(Begin, i));
176 test_iterator J = Begin;
177 J += i;
178 EXPECT_EQ(I, J);
179 EXPECT_EQ(*V[i], Begin[i]);
180
181 EXPECT_NE(I, End);
182 EXPECT_GT(End, I);
183 EXPECT_LT(I, End);
184 EXPECT_GE(I, Begin);
185 EXPECT_LE(Begin, I);
186
187 EXPECT_EQ(i, I - Begin);
188 EXPECT_EQ(i, std::distance(Begin, I));
189 EXPECT_EQ(Begin, I - i);
190
191 test_iterator K = I++;
192 EXPECT_EQ(K, std::prev(I));
193 }
194 EXPECT_EQ(End, I);
195 }
196
TEST(PointeeIteratorTest,SmartPointer)197 TEST(PointeeIteratorTest, SmartPointer) {
198 SmallVector<std::unique_ptr<int>, 4> V;
199 V.push_back(std::make_unique<int>(1));
200 V.push_back(std::make_unique<int>(2));
201 V.push_back(std::make_unique<int>(3));
202 V.push_back(std::make_unique<int>(4));
203
204 typedef pointee_iterator<
205 SmallVectorImpl<std::unique_ptr<int>>::const_iterator>
206 test_iterator;
207
208 test_iterator Begin, End;
209 Begin = V.begin();
210 End = test_iterator(V.end());
211
212 test_iterator I = Begin;
213 for (int i = 0; i < 4; ++i) {
214 EXPECT_EQ(*V[i], *I);
215
216 EXPECT_EQ(I, Begin + i);
217 EXPECT_EQ(I, std::next(Begin, i));
218 test_iterator J = Begin;
219 J += i;
220 EXPECT_EQ(I, J);
221 EXPECT_EQ(*V[i], Begin[i]);
222
223 EXPECT_NE(I, End);
224 EXPECT_GT(End, I);
225 EXPECT_LT(I, End);
226 EXPECT_GE(I, Begin);
227 EXPECT_LE(Begin, I);
228
229 EXPECT_EQ(i, I - Begin);
230 EXPECT_EQ(i, std::distance(Begin, I));
231 EXPECT_EQ(Begin, I - i);
232
233 test_iterator K = I++;
234 EXPECT_EQ(K, std::prev(I));
235 }
236 EXPECT_EQ(End, I);
237 }
238
TEST(PointeeIteratorTest,Range)239 TEST(PointeeIteratorTest, Range) {
240 int A[] = {1, 2, 3, 4};
241 SmallVector<int *, 4> V{&A[0], &A[1], &A[2], &A[3]};
242
243 int I = 0;
244 for (int II : make_pointee_range(V))
245 EXPECT_EQ(A[I++], II);
246 }
247
TEST(PointeeIteratorTest,PointeeType)248 TEST(PointeeIteratorTest, PointeeType) {
249 struct S {
250 int X;
251 bool operator==(const S &RHS) const { return X == RHS.X; };
252 };
253 S A[] = {S{0}, S{1}};
254 SmallVector<S *, 2> V{&A[0], &A[1]};
255
256 pointee_iterator<SmallVectorImpl<S *>::const_iterator, const S> I = V.begin();
257 for (int j = 0; j < 2; ++j, ++I) {
258 EXPECT_EQ(*V[j], *I);
259 }
260 }
261
TEST(FilterIteratorTest,Lambda)262 TEST(FilterIteratorTest, Lambda) {
263 auto IsOdd = [](int N) { return N % 2 == 1; };
264 int A[] = {0, 1, 2, 3, 4, 5, 6};
265 auto Range = make_filter_range(A, IsOdd);
266 SmallVector<int, 3> Actual(Range.begin(), Range.end());
267 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
268 }
269
TEST(FilterIteratorTest,Enumerate)270 TEST(FilterIteratorTest, Enumerate) {
271 auto IsOdd = [](auto N) { return N.value() % 2 == 1; };
272 int A[] = {0, 1, 2, 3, 4, 5, 6};
273 auto Enumerate = llvm::enumerate(A);
274 SmallVector<int> Actual;
275 for (auto IndexedValue : make_filter_range(Enumerate, IsOdd))
276 Actual.push_back(IndexedValue.value());
277 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
278 }
279
TEST(FilterIteratorTest,CallableObject)280 TEST(FilterIteratorTest, CallableObject) {
281 int Counter = 0;
282 struct Callable {
283 int &Counter;
284
285 Callable(int &Counter) : Counter(Counter) {}
286
287 bool operator()(int N) {
288 Counter++;
289 return N % 2 == 1;
290 }
291 };
292 Callable IsOdd(Counter);
293 int A[] = {0, 1, 2, 3, 4, 5, 6};
294 auto Range = make_filter_range(A, IsOdd);
295 EXPECT_EQ(2, Counter);
296 SmallVector<int, 3> Actual(Range.begin(), Range.end());
297 EXPECT_GE(Counter, 7);
298 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
299 }
300
TEST(FilterIteratorTest,FunctionPointer)301 TEST(FilterIteratorTest, FunctionPointer) {
302 bool (*IsOdd)(int) = [](int N) { return N % 2 == 1; };
303 int A[] = {0, 1, 2, 3, 4, 5, 6};
304 auto Range = make_filter_range(A, IsOdd);
305 SmallVector<int, 3> Actual(Range.begin(), Range.end());
306 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
307 }
308
TEST(FilterIteratorTest,Composition)309 TEST(FilterIteratorTest, Composition) {
310 auto IsOdd = [](int N) { return N % 2 == 1; };
311 std::unique_ptr<int> A[] = {std::make_unique<int>(0), std::make_unique<int>(1),
312 std::make_unique<int>(2), std::make_unique<int>(3),
313 std::make_unique<int>(4), std::make_unique<int>(5),
314 std::make_unique<int>(6)};
315 using PointeeIterator = pointee_iterator<std::unique_ptr<int> *>;
316 auto Range = make_filter_range(
317 make_range(PointeeIterator(std::begin(A)), PointeeIterator(std::end(A))),
318 IsOdd);
319 SmallVector<int, 3> Actual(Range.begin(), Range.end());
320 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
321 }
322
TEST(FilterIteratorTest,InputIterator)323 TEST(FilterIteratorTest, InputIterator) {
324 struct InputIterator
325 : iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag> {
326 InputIterator(int *It) : InputIterator::iterator_adaptor_base(It) {}
327 };
328
329 auto IsOdd = [](int N) { return N % 2 == 1; };
330 int A[] = {0, 1, 2, 3, 4, 5, 6};
331 auto Range = make_filter_range(
332 make_range(InputIterator(std::begin(A)), InputIterator(std::end(A))),
333 IsOdd);
334 SmallVector<int, 3> Actual(Range.begin(), Range.end());
335 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
336 }
337
TEST(FilterIteratorTest,ReverseFilterRange)338 TEST(FilterIteratorTest, ReverseFilterRange) {
339 auto IsOdd = [](int N) { return N % 2 == 1; };
340 int A[] = {0, 1, 2, 3, 4, 5, 6};
341
342 // Check basic reversal.
343 auto Range = reverse(make_filter_range(A, IsOdd));
344 SmallVector<int, 3> Actual(Range.begin(), Range.end());
345 EXPECT_EQ((SmallVector<int, 3>{5, 3, 1}), Actual);
346
347 // Check that the reverse of the reverse is the original.
348 auto Range2 = reverse(reverse(make_filter_range(A, IsOdd)));
349 SmallVector<int, 3> Actual2(Range2.begin(), Range2.end());
350 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual2);
351
352 // Check empty ranges.
353 auto Range3 = reverse(make_filter_range(ArrayRef<int>(), IsOdd));
354 SmallVector<int, 0> Actual3(Range3.begin(), Range3.end());
355 EXPECT_EQ((SmallVector<int, 0>{}), Actual3);
356
357 // Check that we don't skip the first element, provided it isn't filtered
358 // away.
359 auto IsEven = [](int N) { return N % 2 == 0; };
360 auto Range4 = reverse(make_filter_range(A, IsEven));
361 SmallVector<int, 4> Actual4(Range4.begin(), Range4.end());
362 EXPECT_EQ((SmallVector<int, 4>{6, 4, 2, 0}), Actual4);
363 }
364
TEST(PointerIterator,Basic)365 TEST(PointerIterator, Basic) {
366 int A[] = {1, 2, 3, 4};
367 pointer_iterator<int *> Begin(std::begin(A)), End(std::end(A));
368 EXPECT_EQ(A, *Begin);
369 ++Begin;
370 EXPECT_EQ(A + 1, *Begin);
371 ++Begin;
372 EXPECT_EQ(A + 2, *Begin);
373 ++Begin;
374 EXPECT_EQ(A + 3, *Begin);
375 ++Begin;
376 EXPECT_EQ(Begin, End);
377 }
378
TEST(PointerIterator,Const)379 TEST(PointerIterator, Const) {
380 int A[] = {1, 2, 3, 4};
381 const pointer_iterator<int *> Begin(std::begin(A));
382 EXPECT_EQ(A, *Begin);
383 EXPECT_EQ(A + 1, std::next(*Begin, 1));
384 EXPECT_EQ(A + 2, std::next(*Begin, 2));
385 EXPECT_EQ(A + 3, std::next(*Begin, 3));
386 EXPECT_EQ(A + 4, std::next(*Begin, 4));
387 }
388
TEST(PointerIterator,Range)389 TEST(PointerIterator, Range) {
390 int A[] = {1, 2, 3, 4};
391 int I = 0;
392 for (int *P : make_pointer_range(A))
393 EXPECT_EQ(A + I++, P);
394 }
395
TEST(ZipIteratorTest,Basic)396 TEST(ZipIteratorTest, Basic) {
397 using namespace std;
398 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
399 SmallVector<bool, 6> odd{1, 1, 0, 1, 1, 1};
400 const char message[] = "yynyyy\0";
401
402 for (auto tup : zip(pi, odd, message)) {
403 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
404 EXPECT_EQ(get<0>(tup) & 0x01 ? 'y' : 'n', get<2>(tup));
405 }
406
407 // note the rvalue
408 for (auto tup : zip(pi, SmallVector<bool, 0>{1, 1, 0, 1, 1})) {
409 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
410 }
411 }
412
TEST(ZipIteratorTest,ZipFirstBasic)413 TEST(ZipIteratorTest, ZipFirstBasic) {
414 using namespace std;
415 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
416 unsigned iters = 0;
417
418 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
419 EXPECT_EQ(get<0>(tup), get<1>(tup) & 0x01);
420 iters += 1;
421 }
422
423 EXPECT_EQ(iters, 4u);
424 }
425
TEST(ZipIteratorTest,ZipLongestBasic)426 TEST(ZipIteratorTest, ZipLongestBasic) {
427 using namespace std;
428 const vector<unsigned> pi{3, 1, 4, 1, 5, 9};
429 const vector<StringRef> e{"2", "7", "1", "8"};
430
431 {
432 // Check left range longer than right.
433 const vector<tuple<Optional<unsigned>, Optional<StringRef>>> expected{
434 make_tuple(3, StringRef("2")), make_tuple(1, StringRef("7")),
435 make_tuple(4, StringRef("1")), make_tuple(1, StringRef("8")),
436 make_tuple(5, None), make_tuple(9, None)};
437 size_t iters = 0;
438 for (auto tup : zip_longest(pi, e)) {
439 EXPECT_EQ(tup, expected[iters]);
440 iters += 1;
441 }
442 EXPECT_EQ(iters, expected.size());
443 }
444
445 {
446 // Check right range longer than left.
447 const vector<tuple<Optional<StringRef>, Optional<unsigned>>> expected{
448 make_tuple(StringRef("2"), 3), make_tuple(StringRef("7"), 1),
449 make_tuple(StringRef("1"), 4), make_tuple(StringRef("8"), 1),
450 make_tuple(None, 5), make_tuple(None, 9)};
451 size_t iters = 0;
452 for (auto tup : zip_longest(e, pi)) {
453 EXPECT_EQ(tup, expected[iters]);
454 iters += 1;
455 }
456 EXPECT_EQ(iters, expected.size());
457 }
458 }
459
TEST(ZipIteratorTest,Mutability)460 TEST(ZipIteratorTest, Mutability) {
461 using namespace std;
462 const SmallVector<unsigned, 4> pi{3, 1, 4, 1, 5, 9};
463 char message[] = "hello zip\0";
464
465 for (auto tup : zip(pi, message, message)) {
466 EXPECT_EQ(get<1>(tup), get<2>(tup));
467 get<2>(tup) = get<0>(tup) & 0x01 ? 'y' : 'n';
468 }
469
470 // note the rvalue
471 for (auto tup : zip(message, "yynyyyzip\0")) {
472 EXPECT_EQ(get<0>(tup), get<1>(tup));
473 }
474 }
475
TEST(ZipIteratorTest,ZipFirstMutability)476 TEST(ZipIteratorTest, ZipFirstMutability) {
477 using namespace std;
478 vector<unsigned> pi{3, 1, 4, 1, 5, 9};
479 unsigned iters = 0;
480
481 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
482 get<1>(tup) = get<0>(tup);
483 iters += 1;
484 }
485
486 EXPECT_EQ(iters, 4u);
487
488 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
489 EXPECT_EQ(get<0>(tup), get<1>(tup));
490 }
491 }
492
TEST(ZipIteratorTest,Filter)493 TEST(ZipIteratorTest, Filter) {
494 using namespace std;
495 vector<unsigned> pi{3, 1, 4, 1, 5, 9};
496
497 unsigned iters = 0;
498 // pi is length 6, but the zip RHS is length 7.
499 auto zipped = zip_first(pi, vector<bool>{1, 1, 0, 1, 1, 1, 0});
500 for (auto tup : make_filter_range(
501 zipped, [](decltype(zipped)::value_type t) { return get<1>(t); })) {
502 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
503 get<0>(tup) += 1;
504 iters += 1;
505 }
506
507 // Should have skipped pi[2].
508 EXPECT_EQ(iters, 5u);
509
510 // Ensure that in-place mutation works.
511 EXPECT_TRUE(all_of(pi, [](unsigned n) { return (n & 0x01) == 0; }));
512 }
513
TEST(ZipIteratorTest,Reverse)514 TEST(ZipIteratorTest, Reverse) {
515 using namespace std;
516 vector<unsigned> ascending{0, 1, 2, 3, 4, 5};
517
518 auto zipped = zip_first(ascending, vector<bool>{0, 1, 0, 1, 0, 1});
519 unsigned last = 6;
520 for (auto tup : reverse(zipped)) {
521 // Check that this is in reverse.
522 EXPECT_LT(get<0>(tup), last);
523 last = get<0>(tup);
524 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
525 }
526
527 auto odds = [](decltype(zipped)::value_type tup) { return get<1>(tup); };
528 last = 6;
529 for (auto tup : make_filter_range(reverse(zipped), odds)) {
530 EXPECT_LT(get<0>(tup), last);
531 last = get<0>(tup);
532 EXPECT_TRUE(get<0>(tup) & 0x01);
533 get<0>(tup) += 1;
534 }
535
536 // Ensure that in-place mutation works.
537 EXPECT_TRUE(all_of(ascending, [](unsigned n) { return (n & 0x01) == 0; }));
538 }
539
TEST(RangeTest,Distance)540 TEST(RangeTest, Distance) {
541 std::vector<int> v1;
542 std::vector<int> v2{1, 2, 3};
543
544 EXPECT_EQ(std::distance(v1.begin(), v1.end()), size(v1));
545 EXPECT_EQ(std::distance(v2.begin(), v2.end()), size(v2));
546 }
547
548 } // anonymous namespace
549