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

Duncan P. N. Exon Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 17 15:55:49 PDT 2016


> On 2016-Aug-17, at 15:06, Pete Cooper via llvm-commits <llvm-commits at lists.llvm.org> wrote:
> 
> 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 {

Do you need to hook this up to the unit test somehow?

> +  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
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list