brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · 6849ccb Raw
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