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 "gtest/gtest.h"
20 // A wrapper around vector which exposes rbegin(), rend().
21 class ReverseOnlyVector
{
25 ReverseOnlyVector(std::initializer_list
<int> list
) : Vec(list
) {}
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(); }
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().
38 class BidirectionalVector
{
39 mutable std::vector
<int> Vec
;
42 BidirectionalVector(std::initializer_list
<int> list
) : Vec(list
) {}
44 typedef std::vector
<int>::iterator iterator
;
45 iterator
begin() const;
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(); }
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.
55 class BidirectionalVectorConsts
{
59 BidirectionalVectorConsts(std::initializer_list
<int> list
) : Vec(list
) {}
61 typedef std::vector
<int>::iterator iterator
;
62 typedef std::vector
<int>::const_iterator const_iterator
;
65 const_iterator
begin() const;
66 const_iterator
end() const;
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(); }
76 /// Check that types with custom iterators work.
77 class CustomIteratorVector
{
78 mutable std::vector
<int> V
;
81 CustomIteratorVector(std::initializer_list
<int> list
) : V(list
) {}
83 typedef std::vector
<int>::iterator iterator
;
84 class reverse_iterator
{
85 std::vector
<int>::iterator I
;
88 reverse_iterator() = default;
89 reverse_iterator(const reverse_iterator
&) = default;
90 reverse_iterator
&operator=(const reverse_iterator
&) = default;
92 explicit reverse_iterator(std::vector
<int>::iterator I
) : I(I
) {}
94 reverse_iterator
&operator++() {
98 reverse_iterator
&operator--() {
102 int &operator*() const { return *std::prev(I
); }
103 int *operator->() const { return &*std::prev(I
); }
104 friend bool operator==(const reverse_iterator
&L
,
105 const reverse_iterator
&R
) {
108 friend bool operator!=(const reverse_iterator
&L
,
109 const reverse_iterator
&R
) {
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()); }
120 template <typename R
> void TestRev(const R
&r
) {
123 EXPECT_EQ(i
, counter
--);
127 template <typename T
> class RangeAdapterLValueTest
: public ::testing::Test
{};
129 typedef ::testing::Types
<std::vector
<int>, std::list
<int>, int[4]>
130 RangeAdapterLValueTestTypes
;
131 TYPED_TEST_SUITE(RangeAdapterLValueTest
, RangeAdapterLValueTestTypes
, );
133 TYPED_TEST(RangeAdapterLValueTest
, TrivialOperation
) {
134 TypeParam v
= {0, 1, 2, 3};
137 const TypeParam c
= {0, 1, 2, 3};
141 template <typename T
> struct RangeAdapterRValueTest
: testing::Test
{};
143 typedef ::testing::Types
<std::vector
<int>, std::list
<int>, CustomIteratorVector
,
144 ReverseOnlyVector
, BidirectionalVector
,
145 BidirectionalVectorConsts
>
146 RangeAdapterRValueTestTypes
;
147 TYPED_TEST_SUITE(RangeAdapterRValueTest
, RangeAdapterRValueTestTypes
, );
149 TYPED_TEST(RangeAdapterRValueTest
, TrivialOperation
) {
150 TestRev(reverse(TypeParam({0, 1, 2, 3})));
153 TYPED_TEST(RangeAdapterRValueTest
, RangeType
) {
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()");
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]");
164 } // anonymous namespace