165 lines · cpp
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-exception6//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 using reverse_iterator = std::vector<int>::reverse_iterator;28 using const_reverse_iterator = std::vector<int>::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 will37// 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 using iterator = std::vector<int>::iterator;45 iterator begin() const;46 iterator end() const;47 48 using reverse_iterator = std::vector<int>::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 const54/// 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 using iterator = std::vector<int>::iterator;62 using const_iterator = std::vector<int>::const_iterator;63 iterator begin();64 iterator end();65 const_iterator begin() const;66 const_iterator end() const;67 68 using reverse_iterator = std::vector<int>::reverse_iterator;69 using const_reverse_iterator = std::vector<int>::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 using iterator = std::vector<int>::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(I); }103 int *operator->() const { return &*std::prev(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 fixture127template <typename T> class RangeAdapterLValueTest : public ::testing::Test {};128 129using RangeAdapterLValueTestTypes =130 ::testing::Types<std::vector<int>, std::list<int>, int[4]>;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 143using RangeAdapterRValueTestTypes =144 ::testing::Types<std::vector<int>, std::list<int>, CustomIteratorVector,145 ReverseOnlyVector, BidirectionalVector,146 BidirectionalVectorConsts>;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 namespace165