[llvm] r278991 - Fix reverse to work on const rbegin()/rend().

Pete Cooper via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 17 15:06:59 PDT 2016


Author: pete
Date: Wed Aug 17 17:06:59 2016
New Revision: 278991

URL: http://llvm.org/viewvc/llvm-project?rev=278991&view=rev
Log:
Fix reverse to work on const rbegin()/rend().

Duncan found that reverse worked on mutable rbegin(), but the has_rbegin
trait didn't work with a const method.  See http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20160815/382890.html
for more details.

Turns out this was already solved in clang with has_getDecl.  Copied that and made it work for rbegin.

This includes the tests Duncan attached to that thread, including the traits test.

Modified:
    llvm/trunk/include/llvm/ADT/STLExtras.h
    llvm/trunk/unittests/ADT/RangeAdapterTest.cpp

Modified: llvm/trunk/include/llvm/ADT/STLExtras.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/STLExtras.h?rev=278991&r1=278990&r2=278991&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/STLExtras.h (original)
+++ llvm/trunk/include/llvm/ADT/STLExtras.h Wed Aug 17 17:06:59 2016
@@ -209,10 +209,19 @@ inline mapped_iterator<ItTy, FuncTy> map
 }
 
 /// \brief Metafunction to determine if type T has a member called rbegin().
-template <typename T> struct has_rbegin {
-  template <typename U> static char(&f(const U &, decltype(&U::rbegin)))[1];
-  static char(&f(...))[2];
-  const static bool value = sizeof(f(std::declval<T>(), nullptr)) == 1;
+template <typename Ty>
+class has_rbegin {
+  typedef char yes[1];
+  typedef char no[2];
+
+  template <typename Inner>
+  static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr);
+
+  template <typename>
+  static no& test(...);
+
+public:
+  static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
 };
 
 // Returns an iterator_range over the given container which iterates in reverse.

Modified: llvm/trunk/unittests/ADT/RangeAdapterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/RangeAdapterTest.cpp?rev=278991&r1=278990&r2=278991&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/RangeAdapterTest.cpp (original)
+++ llvm/trunk/unittests/ADT/RangeAdapterTest.cpp Wed Aug 17 17:06:59 2016
@@ -27,8 +27,11 @@ public:
   ReverseOnlyVector(std::initializer_list<int> list) : Vec(list) {}
 
   typedef std::vector<int>::reverse_iterator reverse_iterator;
+  typedef std::vector<int>::const_reverse_iterator const_reverse_iterator;
   reverse_iterator rbegin() { return Vec.rbegin(); }
   reverse_iterator rend() { return Vec.rend(); }
+  const_reverse_iterator rbegin() const { return Vec.rbegin(); }
+  const_reverse_iterator rend() const { return Vec.rend(); }
 };
 
 // A wrapper around vector which exposes begin(), end(), rbegin() and rend().
@@ -49,6 +52,29 @@ public:
   reverse_iterator rend() { return Vec.rend(); }
 };
 
+/// This is the same as BidirectionalVector but with the addition of const
+/// begin/rbegin methods to ensure that the type traits for has_rbegin works.
+class BidirectionalVectorConsts {
+  std::vector<int> Vec;
+
+public:
+  BidirectionalVectorConsts(std::initializer_list<int> list) : Vec(list) {}
+
+  typedef std::vector<int>::iterator iterator;
+  typedef std::vector<int>::const_iterator const_iterator;
+  iterator begin();
+  iterator end();
+  const_iterator begin() const;
+  const_iterator end() const;
+
+  typedef std::vector<int>::reverse_iterator reverse_iterator;
+  typedef std::vector<int>::const_reverse_iterator const_reverse_iterator;
+  reverse_iterator rbegin() { return Vec.rbegin(); }
+  reverse_iterator rend() { return Vec.rend(); }
+  const_reverse_iterator rbegin() const { return Vec.rbegin(); }
+  const_reverse_iterator rend() const { return Vec.rend(); }
+};
+
 template <typename R> void TestRev(const R &r) {
   int counter = 3;
   for (int i : r)
@@ -80,4 +106,8 @@ TYPED_TEST(RangeAdapterRValueTest, Trivi
   TestRev(reverse(TypeParam({0, 1, 2, 3})));
 }
 
+TYPED_TEST(RangeAdapterRValueTest, HasRbegin) {
+  EXPECT_TRUE(has_rbegin<TypeParam>::value);
+}
+
 } // anonymous namespace




More information about the llvm-commits mailing list