llvm.org GIT mirror llvm / 639ec3d
Reapply "Add reverse(ContainerTy) range adapter." This reverts commit r243567, which ultimately reapplies r243563. The fix here was to use std::enable_if for overload resolution. Thanks to David Blaikie for lots of help on this, and for the extra tests! Original commit message follows: For cases where we needed a foreach loop in reverse over a container, we had to do something like for (const GlobalValue *GV : make_range(TypeInfos.rbegin(), TypeInfos.rend())) { This provides a convenience method which shortens this to for (const GlobalValue *GV : reverse(TypeInfos)) { There are 2 versions of this, with a preference to the rbegin() version. The first uses rbegin() and rend() to construct an iterator_range. The second constructs an iterator_range from the begin() and end() methods wrapped in std::reverse_iterator's. Reviewed by David Blaikie. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243581 91177308-0d34-0410-b5e6-96231b3b80d8 Pete Cooper 5 years ago
4 changed file(s) with 120 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
193193 template
194194 inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) {
195195 return mapped_iterator(I, F);
196 }
197
198 /// \brief Metafunction to determine if type T has a member called rbegin().
199 template struct has_rbegin {
200 template static char(&f(const U &, decltype(&U::rbegin)))[1];
201 static char(&f(...))[2];
202 const static bool value = sizeof(f(std::declval(), nullptr)) == 1;
203 };
204
205 // Returns an iterator_range over the given container which iterates in reverse.
206 // Note that the container must have rbegin()/rend() methods for this to work.
207 template
208 auto reverse(ContainerTy &&C,
209 typename std::enable_if::value>::type * =
210 nullptr) -> decltype(make_range(C.rbegin(), C.rend())) {
211 return make_range(C.rbegin(), C.rend());
212 }
213
214 // Returns a std::reverse_iterator wrapped around the given iterator.
215 template
216 std::reverse_iterator make_reverse_iterator(IteratorTy It) {
217 return std::reverse_iterator(It);
218 }
219
220 // Returns an iterator_range over the given container which iterates in reverse.
221 // Note that the container must have begin()/end() methods which return
222 // bidirectional iterators for this to work.
223 template
224 auto reverse(
225 ContainerTy &&C,
226 typename std::enable_if::value>::type * = nullptr)
227 -> decltype(make_range(make_reverse_iterator(std::end(C)),
228 make_reverse_iterator(std::begin(C)))) {
229 return make_range(make_reverse_iterator(std::end(C)),
230 make_reverse_iterator(std::begin(C)));
196231 }
197232
198233 //===----------------------------------------------------------------------===//
114114 Entry = TypeInfos.size();
115115 }
116116
117 for (const GlobalValue *GV : make_range(TypeInfos.rbegin(),
118 TypeInfos.rend())) {
117 for (const GlobalValue *GV : reverse(TypeInfos)) {
119118 if (VerboseAsm)
120119 Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--));
121120 Asm->EmitTTypeReference(GV, TTypeEncoding);
2727 PointerIntPairTest.cpp
2828 PointerUnionTest.cpp
2929 PostOrderIteratorTest.cpp
30 RangeAdapterTest.cpp
3031 SCCIteratorTest.cpp
3132 SmallPtrSetTest.cpp
3233 SmallStringTest.cpp
0 //===- RangeAdapterTest.cpp - Unit tests for range adapters --------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/ADT/iterator_range.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "gtest/gtest.h"
12
13 #include
14 #include
15 #include
16
17 using namespace llvm;
18
19 namespace {
20
21 // A wrapper around vector which exposes rbegin(), rend().
22 class ReverseOnlyVector {
23 std::vector Vec;
24
25 public:
26 ReverseOnlyVector(std::initializer_list list) : Vec(list) {}
27
28 typedef std::vector::reverse_iterator reverse_iterator;
29 reverse_iterator rbegin() { return Vec.rbegin(); }
30 reverse_iterator rend() { return Vec.rend(); }
31 };
32
33 // A wrapper around vector which exposes begin(), end(), rbegin() and rend().
34 // begin() and end() don't have implementations as this ensures that we will
35 // get a linker error if reverse() chooses begin()/end() over rbegin(), rend().
36 class BidirectionalVector {
37 std::vector Vec;
38
39 public:
40 BidirectionalVector(std::initializer_list list) : Vec(list) {}
41
42 typedef std::vector::iterator iterator;
43 iterator begin();
44 iterator end();
45
46 typedef std::vector::reverse_iterator reverse_iterator;
47 reverse_iterator rbegin() { return Vec.rbegin(); }
48 reverse_iterator rend() { return Vec.rend(); }
49 };
50
51 template void TestRev(const R &r) {
52 int counter = 3;
53 for (int i : r)
54 EXPECT_EQ(i, counter--);
55 }
56
57 // Test fixture
58 template class RangeAdapterLValueTest : public ::testing::Test {};
59
60 typedef ::testing::Types, std::list, int[4]>
61 RangeAdapterLValueTestTypes;
62 TYPED_TEST_CASE(RangeAdapterLValueTest, RangeAdapterLValueTestTypes);
63
64 TYPED_TEST(RangeAdapterLValueTest, TrivialOperation) {
65 TypeParam v = {0, 1, 2, 3};
66 TestRev(reverse(v));
67
68 const TypeParam c = {0, 1, 2, 3};
69 TestRev(reverse(c));
70 }
71
72 template struct RangeAdapterRValueTest : testing::Test {};
73
74 typedef ::testing::Types, std::list, ReverseOnlyVector,
75 BidirectionalVector> RangeAdapterRValueTestTypes;
76 TYPED_TEST_CASE(RangeAdapterRValueTest, RangeAdapterRValueTestTypes);
77
78 TYPED_TEST(RangeAdapterRValueTest, TrivialOperation) {
79 TestRev(reverse(TypeParam({0, 1, 2, 3})));
80 }
81
82 } // anonymous namespace