1//===- RangeAdapterTest.cpp - Unit tests for range adapters --------------===//
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#include <iterator>
13#include <list>
14#include <vector>
15
16using namespace llvm;
17
18namespace {
19
20// A wrapper around vector which exposes rbegin(), rend().
21class ReverseOnlyVector {
22 std::vector<int> Vec;
23
24public:
25 ReverseOnlyVector(std::initializer_list<int> list) : Vec(list) {}
26
27 typedef std::vector<int>::reverse_iterator reverse_iterator;
28 typedef std::vector<int>::const_reverse_iterator const_reverse_iterator;
29 reverse_iterator rbegin() { return Vec.rbegin(); }
30 reverse_iterator rend() { return Vec.rend(); }
31 const_reverse_iterator rbegin() const { return Vec.rbegin(); }
32 const_reverse_iterator rend() const { return Vec.rend(); }
33};
34
35// A wrapper around vector which exposes begin(), end(), rbegin() and rend().
36// begin() and end() don't have implementations as this ensures that we will
37// get a linker error if reverse() chooses begin()/end() over rbegin(), rend().
38class BidirectionalVector {
39 mutable std::vector<int> Vec;
40
41public:
42 BidirectionalVector(std::initializer_list<int> list) : Vec(list) {}
43
44 typedef std::vector<int>::iterator iterator;
45 iterator begin() const;
46 iterator end() const;
47
48 typedef std::vector<int>::reverse_iterator reverse_iterator;
49 reverse_iterator rbegin() const { return Vec.rbegin(); }
50 reverse_iterator rend() const { return Vec.rend(); }
51};
52
53/// This is the same as BidirectionalVector but with the addition of const
54/// begin/rbegin methods to ensure that the type traits for has_rbegin works.
55class BidirectionalVectorConsts {
56 std::vector<int> Vec;
57
58public:
59 BidirectionalVectorConsts(std::initializer_list<int> list) : Vec(list) {}
60
61 typedef std::vector<int>::iterator iterator;
62 typedef std::vector<int>::const_iterator const_iterator;
63 iterator begin();
64 iterator end();
65 const_iterator begin() const;
66 const_iterator end() const;
67
68 typedef std::vector<int>::reverse_iterator reverse_iterator;
69 typedef std::vector<int>::const_reverse_iterator const_reverse_iterator;
70 reverse_iterator rbegin() { return Vec.rbegin(); }
71 reverse_iterator rend() { return Vec.rend(); }
72 const_reverse_iterator rbegin() const { return Vec.rbegin(); }
73 const_reverse_iterator rend() const { return Vec.rend(); }
74};
75
76/// Check that types with custom iterators work.
77class CustomIteratorVector {
78 mutable std::vector<int> V;
79
80public:
81 CustomIteratorVector(std::initializer_list<int> list) : V(list) {}
82
83 typedef std::vector<int>::iterator iterator;
84 class reverse_iterator {
85 std::vector<int>::iterator I;
86
87 public:
88 reverse_iterator() = default;
89 reverse_iterator(const reverse_iterator &) = default;
90 reverse_iterator &operator=(const reverse_iterator &) = default;
91
92 explicit reverse_iterator(std::vector<int>::iterator I) : I(I) {}
93
94 reverse_iterator &operator++() {
95 --I;
96 return *this;
97 }
98 reverse_iterator &operator--() {
99 ++I;
100 return *this;
101 }
102 int &operator*() const { return *std::prev(x: I); }
103 int *operator->() const { return &*std::prev(x: I); }
104 friend bool operator==(const reverse_iterator &L,
105 const reverse_iterator &R) {
106 return L.I == R.I;
107 }
108 friend bool operator!=(const reverse_iterator &L,
109 const reverse_iterator &R) {
110 return !(L == R);
111 }
112 };
113
114 iterator begin() const { return V.begin(); }
115 iterator end() const { return V.end(); }
116 reverse_iterator rbegin() const { return reverse_iterator(V.end()); }
117 reverse_iterator rend() const { return reverse_iterator(V.begin()); }
118};
119
120template <typename R> void TestRev(const R &r) {
121 int counter = 3;
122 for (int i : r)
123 EXPECT_EQ(i, counter--);
124}
125
126// Test fixture
127template <typename T> class RangeAdapterLValueTest : public ::testing::Test {};
128
129typedef ::testing::Types<std::vector<int>, std::list<int>, int[4]>
130 RangeAdapterLValueTestTypes;
131TYPED_TEST_SUITE(RangeAdapterLValueTest, RangeAdapterLValueTestTypes, );
132
133TYPED_TEST(RangeAdapterLValueTest, TrivialOperation) {
134 TypeParam v = {0, 1, 2, 3};
135 TestRev(reverse(v));
136
137 const TypeParam c = {0, 1, 2, 3};
138 TestRev(reverse(c));
139}
140
141template <typename T> struct RangeAdapterRValueTest : testing::Test {};
142
143typedef ::testing::Types<std::vector<int>, std::list<int>, CustomIteratorVector,
144 ReverseOnlyVector, BidirectionalVector,
145 BidirectionalVectorConsts>
146 RangeAdapterRValueTestTypes;
147TYPED_TEST_SUITE(RangeAdapterRValueTest, RangeAdapterRValueTestTypes, );
148
149TYPED_TEST(RangeAdapterRValueTest, TrivialOperation) {
150 TestRev(reverse(TypeParam({0, 1, 2, 3})));
151}
152
153TYPED_TEST(RangeAdapterRValueTest, RangeType) {
154 static_assert(
155 std::is_same_v<decltype(reverse(std::declval<TypeParam>()).begin()),
156 decltype(std::declval<TypeParam>().rbegin())>,
157 "reverse().begin() should have the same type as rbegin()");
158 static_assert(
159 std::is_same_v<decltype(reverse(std::declval<const TypeParam>()).begin()),
160 decltype(std::declval<const TypeParam>().rbegin())>,
161 "reverse().begin() should have the same type as rbegin() [const]");
162}
163
164} // anonymous namespace
165

source code of llvm/unittests/ADT/RangeAdapterTest.cpp