1 //===- RangeAdapterTest.cpp - Unit tests for range adapters --------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/STLExtras.h"
10 #include "llvm/ADT/iterator_range.h"
11 #include "gtest/gtest.h"
21 // A wrapper around vector which exposes rbegin(), rend().
22 class ReverseOnlyVector
{
26 ReverseOnlyVector(std::initializer_list
<int> list
) : Vec(list
) {}
28 typedef std::vector
<int>::reverse_iterator reverse_iterator
;
29 typedef std::vector
<int>::const_reverse_iterator const_reverse_iterator
;
30 reverse_iterator
rbegin() { return Vec
.rbegin(); }
31 reverse_iterator
rend() { return Vec
.rend(); }
32 const_reverse_iterator
rbegin() const { return Vec
.rbegin(); }
33 const_reverse_iterator
rend() const { return Vec
.rend(); }
36 // A wrapper around vector which exposes begin(), end(), rbegin() and rend().
37 // begin() and end() don't have implementations as this ensures that we will
38 // get a linker error if reverse() chooses begin()/end() over rbegin(), rend().
39 class BidirectionalVector
{
40 mutable std::vector
<int> Vec
;
43 BidirectionalVector(std::initializer_list
<int> list
) : Vec(list
) {}
45 typedef std::vector
<int>::iterator iterator
;
46 iterator
begin() const;
49 typedef std::vector
<int>::reverse_iterator reverse_iterator
;
50 reverse_iterator
rbegin() const { return Vec
.rbegin(); }
51 reverse_iterator
rend() const { return Vec
.rend(); }
54 /// This is the same as BidirectionalVector but with the addition of const
55 /// begin/rbegin methods to ensure that the type traits for has_rbegin works.
56 class BidirectionalVectorConsts
{
60 BidirectionalVectorConsts(std::initializer_list
<int> list
) : Vec(list
) {}
62 typedef std::vector
<int>::iterator iterator
;
63 typedef std::vector
<int>::const_iterator const_iterator
;
66 const_iterator
begin() const;
67 const_iterator
end() const;
69 typedef std::vector
<int>::reverse_iterator reverse_iterator
;
70 typedef std::vector
<int>::const_reverse_iterator const_reverse_iterator
;
71 reverse_iterator
rbegin() { return Vec
.rbegin(); }
72 reverse_iterator
rend() { return Vec
.rend(); }
73 const_reverse_iterator
rbegin() const { return Vec
.rbegin(); }
74 const_reverse_iterator
rend() const { return Vec
.rend(); }
77 /// Check that types with custom iterators work.
78 class CustomIteratorVector
{
79 mutable std::vector
<int> V
;
82 CustomIteratorVector(std::initializer_list
<int> list
) : V(list
) {}
84 typedef std::vector
<int>::iterator iterator
;
85 class reverse_iterator
{
86 std::vector
<int>::iterator I
;
89 reverse_iterator() = default;
90 reverse_iterator(const reverse_iterator
&) = default;
91 reverse_iterator
&operator=(const reverse_iterator
&) = default;
93 explicit reverse_iterator(std::vector
<int>::iterator I
) : I(I
) {}
95 reverse_iterator
&operator++() {
99 reverse_iterator
&operator--() {
103 int &operator*() const { return *std::prev(I
); }
104 int *operator->() const { return &*std::prev(I
); }
105 friend bool operator==(const reverse_iterator
&L
,
106 const reverse_iterator
&R
) {
109 friend bool operator!=(const reverse_iterator
&L
,
110 const reverse_iterator
&R
) {
115 iterator
begin() const { return V
.begin(); }
116 iterator
end() const { return V
.end(); }
117 reverse_iterator
rbegin() const { return reverse_iterator(V
.end()); }
118 reverse_iterator
rend() const { return reverse_iterator(V
.begin()); }
121 template <typename R
> void TestRev(const R
&r
) {
124 EXPECT_EQ(i
, counter
--);
128 template <typename T
> class RangeAdapterLValueTest
: public ::testing::Test
{};
130 typedef ::testing::Types
<std::vector
<int>, std::list
<int>, int[4]>
131 RangeAdapterLValueTestTypes
;
132 TYPED_TEST_CASE(RangeAdapterLValueTest
, RangeAdapterLValueTestTypes
);
134 TYPED_TEST(RangeAdapterLValueTest
, TrivialOperation
) {
135 TypeParam v
= {0, 1, 2, 3};
138 const TypeParam c
= {0, 1, 2, 3};
142 template <typename T
> struct RangeAdapterRValueTest
: testing::Test
{};
144 typedef ::testing::Types
<std::vector
<int>, std::list
<int>, CustomIteratorVector
,
145 ReverseOnlyVector
, BidirectionalVector
,
146 BidirectionalVectorConsts
>
147 RangeAdapterRValueTestTypes
;
148 TYPED_TEST_CASE(RangeAdapterRValueTest
, RangeAdapterRValueTestTypes
);
150 TYPED_TEST(RangeAdapterRValueTest
, TrivialOperation
) {
151 TestRev(reverse(TypeParam({0, 1, 2, 3})));
154 TYPED_TEST(RangeAdapterRValueTest
, HasRbegin
) {
155 static_assert(has_rbegin
<TypeParam
>::value
, "rbegin() should be defined");
158 TYPED_TEST(RangeAdapterRValueTest
, RangeType
) {
161 decltype(reverse(*static_cast<TypeParam
*>(nullptr)).begin()),
162 decltype(static_cast<TypeParam
*>(nullptr)->rbegin())>::value
,
163 "reverse().begin() should have the same type as rbegin()");
166 decltype(reverse(*static_cast<const TypeParam
*>(nullptr)).begin()),
167 decltype(static_cast<const TypeParam
*>(nullptr)->rbegin())>::value
,
168 "reverse().begin() should have the same type as rbegin() [const]");
171 } // anonymous namespace