[llvm] r287722 - Add some searching functions for ArrayRef<T>.

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 28 10:23:23 PST 2016


On Mon, Nov 28, 2016 at 10:19 AM Zachary Turner <zturner at google.com> wrote:

> Having a single type for cost and mutable would be great, if we could make
> it work.  Seems like a huge change across the codebase, but probably worth
> it if myself or someone gets some cycles to do it.
>

Yep - big, but fairly mechanical change. If you/anyone else wants to do
this, I'd suggest floating it on llvm-dev first, just so everyone's aware
of the ArrayRef<T> -> ArrayRef<const T> change that would fall out of this.


> And good point about having drop_front call slice.  I can make it parallel
> the interface of ArrayRef for now, until we figure out what to do about
> constness.
>

Yep yep


>
> On Mon, Nov 28, 2016 at 10:16 AM David Blaikie <dblaikie at gmail.com> wrote:
>
> On Tue, Nov 22, 2016 at 3:32 PM Zachary Turner via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
> Author: zturner
> Date: Tue Nov 22 17:22:19 2016
> New Revision: 287722
>
> URL: http://llvm.org/viewvc/llvm-project?rev=287722&view=rev
> Log:
> Add some searching functions for ArrayRef<T>.
>
> Differential Revision: https://reviews.llvm.org/D26999
>
> Modified:
>     llvm/trunk/include/llvm/ADT/ArrayRef.h
>     llvm/trunk/include/llvm/ADT/STLExtras.h
>     llvm/trunk/unittests/ADT/ArrayRefTest.cpp
>
> Modified: llvm/trunk/include/llvm/ADT/ArrayRef.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ArrayRef.h?rev=287722&r1=287721&r2=287722&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/ArrayRef.h (original)
> +++ llvm/trunk/include/llvm/ADT/ArrayRef.h Tue Nov 22 17:22:19 2016
> @@ -12,6 +12,7 @@
>
>  #include "llvm/ADT/Hashing.h"
>  #include "llvm/ADT/None.h"
> +#include "llvm/ADT/STLExtras.h"
>  #include "llvm/ADT/SmallVector.h"
>  #include <array>
>  #include <vector>
> @@ -165,12 +166,6 @@ namespace llvm {
>        return std::equal(begin(), end(), RHS.begin());
>      }
>
> -    /// slice(n) - Chop off the first N elements of the array.
> -    ArrayRef<T> slice(size_t N) const {
> -      assert(N <= size() && "Invalid specifier");
> -      return ArrayRef<T>(data()+N, size()-N);
>
>
> This might be easier written as ArrayRef(begin() + N, end()) - similar
> suggestion in MutableArrayRef. (worth adding a CRTP base to implement some
> of these common functions in both? - alternatively I'll float the
> suggestion I made when Chris originally committed MutableArrayRef: Maybe we
> just fix ArrayRef<T> -> ArrayRef<const T> and ArrayRef<T> is
> MutableArrayRef<T> and there's no need for two types, etc)
>
> (note you don't need to specify <T> when referencing ArrayRef<T> from
> within the class itself - applies across this change)
>
>
> -    }
> -
>      /// slice(n, m) - Chop off the first N elements of the array, and
> keep M
>      /// elements in the array.
>      ArrayRef<T> slice(size_t N, size_t M) const {
> @@ -178,6 +173,9 @@ namespace llvm {
>        return ArrayRef<T>(data()+N, M);
>      }
>
> +    /// slice(n) - Chop off the first N elements of the array.
>
>
> This is an alias for drop_front below, right? Should one call the other?
>
>
> +    ArrayRef<T> slice(size_t N) const { return slice(N, size() - N); }
> +
>      /// \brief Drop the first \p N elements of the array.
>      ArrayRef<T> drop_front(size_t N = 1) const {
>        assert(size() >= N && "Dropping more elements than exist");
> @@ -190,6 +188,18 @@ namespace llvm {
>        return slice(0, size() - N);
>      }
>
> +    /// \brief Return a copy of *this with the first N elements
> satisfying the
> +    /// given predicate removed.
> +    template <class PredicateT> ArrayRef<T> drop_while(PredicateT Pred)
> const {
> +      return ArrayRef<T>(find_if_not(*this, Pred), end());
> +    }
> +
> +    /// \brief Return a copy of *this with the first N elements not
> satisfying
> +    /// the given predicate removed.
> +    template <class PredicateT> ArrayRef<T> drop_until(PredicateT Pred)
> const {
> +      return ArrayRef<T>(find_if(*this, Pred), end());
> +    }
> +
>      /// \brief Return a copy of *this with only the first \p N elements.
>      ArrayRef<T> take_front(size_t N = 1) const {
>        if (N >= size())
> @@ -204,6 +214,18 @@ namespace llvm {
>        return drop_front(size() - N);
>      }
>
> +    /// \brief Return the first N elements of this Array that satisfy the
> given
> +    /// predicate.
> +    template <class PredicateT> ArrayRef<T> take_while(PredicateT Pred)
> const {
> +      return ArrayRef<T>(begin(), find_if_not(*this, Pred));
> +    }
> +
> +    /// \brief Return the first N elements of this Array that don't
> satisfy the
> +    /// given predicate.
> +    template <class PredicateT> ArrayRef<T> take_until(PredicateT Pred)
> const {
> +      return ArrayRef<T>(begin(), find_if(*this, Pred));
> +    }
> +
>      /// @}
>      /// @name Operator Overloads
>      /// @{
> @@ -317,17 +339,16 @@ namespace llvm {
>        return data()[this->size()-1];
>      }
>
> -    /// slice(n) - Chop off the first N elements of the array.
> -    MutableArrayRef<T> slice(size_t N) const {
> -      assert(N <= this->size() && "Invalid specifier");
> -      return MutableArrayRef<T>(data()+N, this->size()-N);
> -    }
> -
>      /// slice(n, m) - Chop off the first N elements of the array, and
> keep M
>      /// elements in the array.
>      MutableArrayRef<T> slice(size_t N, size_t M) const {
> -      assert(N+M <= this->size() && "Invalid specifier");
> -      return MutableArrayRef<T>(data()+N, M);
> +      assert(N + M <= this->size() && "Invalid specifier");
> +      return MutableArrayRef<T>(this->data() + N, M);
> +    }
> +
> +    /// slice(n) - Chop off the first N elements of the array.
> +    MutableArrayRef<T> slice(size_t N) const {
> +      return slice(N, this->size() - N);
>      }
>
>      /// \brief Drop the first \p N elements of the array.
> @@ -341,6 +362,20 @@ namespace llvm {
>        return slice(0, this->size() - N);
>      }
>
> +    /// \brief Return a copy of *this with the first N elements
> satisfying the
> +    /// given predicate removed.
> +    template <class PredicateT>
> +    MutableArrayRef<T> drop_while(PredicateT Pred) const {
> +      return MutableArrayRef<T>(find_if_not(*this, Pred), end());
> +    }
> +
> +    /// \brief Return a copy of *this with the first N elements not
> satisfying
> +    /// the given predicate removed.
> +    template <class PredicateT>
> +    MutableArrayRef<T> drop_until(PredicateT Pred) const {
> +      return MutableArrayRef<T>(find_if(*this, Pred), end());
> +    }
> +
>      /// \brief Return a copy of *this with only the first \p N elements.
>      MutableArrayRef<T> take_front(size_t N = 1) const {
>        if (N >= this->size())
> @@ -355,6 +390,20 @@ namespace llvm {
>        return drop_front(this->size() - N);
>      }
>
> +    /// \brief Return the first N elements of this Array that satisfy the
> given
> +    /// predicate.
> +    template <class PredicateT>
> +    MutableArrayRef<T> take_while(PredicateT Pred) const {
> +      return MutableArrayRef<T>(begin(), find_if_not(*this, Pred));
> +    }
> +
> +    /// \brief Return the first N elements of this Array that don't
> satisfy the
> +    /// given predicate.
> +    template <class PredicateT>
> +    MutableArrayRef<T> take_until(PredicateT Pred) const {
> +      return MutableArrayRef<T>(begin(), find_if(*this, Pred));
> +    }
> +
>      /// @}
>      /// @name Operator Overloads
>      /// @{
>
> Modified: llvm/trunk/include/llvm/ADT/STLExtras.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/STLExtras.h?rev=287722&r1=287721&r2=287722&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/STLExtras.h (original)
> +++ llvm/trunk/include/llvm/ADT/STLExtras.h Tue Nov 22 17:22:19 2016
> @@ -622,6 +622,11 @@ auto find_if(R &&Range, const T &Pred) -
>    return std::find_if(Range.begin(), Range.end(), Pred);
>  }
>
> +template <typename R, class PredicateT>
> +auto find_if_not(R &&Range, PredicateT Pred) -> decltype(Range.begin()) {
> +  return std::find_if_not(Range.begin(), Range.end(), Pred);
> +}
> +
>  /// Provide wrappers to std::remove_if which take ranges instead of
> having to
>  /// pass begin/end explicitly.
>  template<typename R, class UnaryPredicate>
>
> Modified: llvm/trunk/unittests/ADT/ArrayRefTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/ArrayRefTest.cpp?rev=287722&r1=287721&r2=287722&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/ADT/ArrayRefTest.cpp (original)
> +++ llvm/trunk/unittests/ADT/ArrayRefTest.cpp Tue Nov 22 17:22:19 2016
> @@ -102,6 +102,28 @@ TEST(ArrayRefTest, DropFront) {
>    EXPECT_EQ(1U, AR3.drop_front(AR3.size() - 1).size());
>  }
>
> +TEST(ArrayRefTest, DropWhile) {
> +  static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
> +  ArrayRef<int> AR1(TheNumbers);
> +  ArrayRef<int> Expected = AR1.drop_front(3);
> +  EXPECT_EQ(Expected, AR1.drop_while([](const int &N) { return N % 2 ==
> 1; }));
> +
> +  EXPECT_EQ(AR1, AR1.drop_while([](const int &N) { return N < 0; }));
> +  EXPECT_EQ(ArrayRef<int>(),
> +            AR1.drop_while([](const int &N) { return N > 0; }));
> +}
> +
> +TEST(ArrayRefTest, DropUntil) {
> +  static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
> +  ArrayRef<int> AR1(TheNumbers);
> +  ArrayRef<int> Expected = AR1.drop_front(3);
> +  EXPECT_EQ(Expected, AR1.drop_until([](const int &N) { return N % 2 ==
> 0; }));
> +
> +  EXPECT_EQ(ArrayRef<int>(),
> +            AR1.drop_until([](const int &N) { return N < 0; }));
> +  EXPECT_EQ(AR1, AR1.drop_until([](const int &N) { return N > 0; }));
> +}
> +
>  TEST(ArrayRefTest, TakeBack) {
>    static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};
>    ArrayRef<int> AR1(TheNumbers);
> @@ -116,6 +138,28 @@ TEST(ArrayRefTest, TakeFront) {
>    EXPECT_TRUE(AR1.take_front(2).equals(AR2));
>  }
>
> +TEST(ArrayRefTest, TakeWhile) {
> +  static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
> +  ArrayRef<int> AR1(TheNumbers);
> +  ArrayRef<int> Expected = AR1.take_front(3);
> +  EXPECT_EQ(Expected, AR1.take_while([](const int &N) { return N % 2 ==
> 1; }));
> +
> +  EXPECT_EQ(ArrayRef<int>(),
> +            AR1.take_while([](const int &N) { return N < 0; }));
> +  EXPECT_EQ(AR1, AR1.take_while([](const int &N) { return N > 0; }));
> +}
> +
> +TEST(ArrayRefTest, TakeUntil) {
> +  static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
> +  ArrayRef<int> AR1(TheNumbers);
> +  ArrayRef<int> Expected = AR1.take_front(3);
> +  EXPECT_EQ(Expected, AR1.take_until([](const int &N) { return N % 2 ==
> 0; }));
> +
> +  EXPECT_EQ(AR1, AR1.take_until([](const int &N) { return N < 0; }));
> +  EXPECT_EQ(ArrayRef<int>(),
> +            AR1.take_until([](const int &N) { return N > 0; }));
> +}
> +
>  TEST(ArrayRefTest, Equals) {
>    static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8};
>    ArrayRef<int> AR1(A1);
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161128/498fe867/attachment.html>


More information about the llvm-commits mailing list