[llvm][ADT] Add deduction guides for `MutableArrayRef`
authorJoe Loser <joeloser@fastmail.com>
Mon, 9 Jan 2023 22:37:11 +0000 (15:37 -0700)
committerJoe Loser <joeloser@fastmail.com>
Tue, 10 Jan 2023 20:02:34 +0000 (13:02 -0700)
Similar to https://reviews.llvm.org/D140896, this adds deduction guides for the
counterpart of `ArrayRef`: `MutableArrayRef`.  The update plan is the following:

1) Add deduction guides for `MutableArrayRef`.
2) Change uses in-tree from `makeMutableArrayRef` to use deduction guides
3) Mark `makeMutableArrayRef` as deprecated for some time before removing to
   give downstream users time to update.

The deduction guides are similar to those provided by the `makeMutableArrayRef`
function templates, except we don't need one explicitly from `MutableArrayRef`.

Differential Revision: https://reviews.llvm.org/D141327

llvm/include/llvm/ADT/ArrayRef.h
llvm/unittests/ADT/ArrayRefTest.cpp

index f2f761a..bad1fb5 100644 (file)
@@ -574,6 +574,36 @@ namespace llvm {
     return ArrayRef<T>(Arr);
   }
 
+  /// @name MutableArrayRef Deduction guides
+  /// @{
+  /// Deduction guide to construct a `MutableArrayRef` from a single element
+  template <class T> MutableArrayRef(T &OneElt) -> MutableArrayRef<T>;
+
+  /// Deduction guide to construct a `MutableArrayRef` from a pointer and
+  /// length.
+  template <class T>
+  MutableArrayRef(T *data, size_t length) -> MutableArrayRef<T>;
+
+  /// Deduction guide to construct a `MutableArrayRef` from a `SmallVector`.
+  template <class T>
+  MutableArrayRef(SmallVectorImpl<T> &Vec) -> MutableArrayRef<T>;
+
+  template <class T, unsigned N>
+  MutableArrayRef(SmallVector<T, N> &Vec) -> MutableArrayRef<T>;
+
+  /// Deduction guide to construct a `MutableArrayRef` from a `std::vector`.
+  template <class T> MutableArrayRef(std::vector<T> &Vec) -> MutableArrayRef<T>;
+
+  /// Deduction guide to construct a `MutableArrayRef` from a `std::array`.
+  template <class T, std::size_t N>
+  MutableArrayRef(std::array<T, N> &Vec) -> MutableArrayRef<T>;
+
+  /// Deduction guide to construct a `MutableArrayRef` from a C array.
+  template <typename T, size_t N>
+  MutableArrayRef(T (&Arr)[N]) -> MutableArrayRef<T>;
+
+  /// @}
+
   /// Construct a MutableArrayRef from a single element.
   template<typename T>
   MutableArrayRef<T> makeMutableArrayRef(T &OneElt) {
index 0aea5a9..13a9d56 100644 (file)
@@ -297,4 +297,94 @@ TEST(ArrayRefTest, makeMutableArrayRef) {
   EXPECT_EQ(ER.size(), E.size());
 }
 
+TEST(ArrayRefTest, MutableArrayRefDeductionGuides) {
+  // Single element
+  {
+    int x = 0;
+    auto aref = MutableArrayRef(x);
+    static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);
+    EXPECT_EQ(aref.data(), &x);
+    EXPECT_EQ(aref.size(), 1u);
+
+    // Make sure it's mutable still
+    aref[0] = 1;
+    EXPECT_EQ(x, 1);
+  }
+
+  // Pointer + length
+  {
+    int x[] = {0, 1, 2, 3};
+    auto aref = MutableArrayRef(&x[0], 4);
+    static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);
+    EXPECT_EQ(aref.data(), &x[0]);
+    EXPECT_EQ(aref.size(), 4u);
+  }
+
+  // // Pointer + pointer
+  {
+    int x[] = {0, 1, 2, 3};
+    auto aref = MutableArrayRef(std::begin(x), std::end(x));
+    static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);
+    EXPECT_EQ(aref.data(), &x[0]);
+    EXPECT_EQ(aref.size(), 4u);
+  }
+
+  // SmallVector
+  {
+    SmallVector<int> sv1;
+    SmallVectorImpl<int> &sv2 = sv1;
+    sv1.resize(5);
+    auto aref1 = MutableArrayRef(sv1);
+    auto aref2 = MutableArrayRef(sv2);
+    static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref1)>);
+    static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref2)>);
+    EXPECT_EQ(aref1.data(), sv1.data());
+    EXPECT_EQ(aref1.size(), sv1.size());
+    EXPECT_EQ(aref2.data(), sv2.data());
+    EXPECT_EQ(aref2.size(), sv2.size());
+  }
+
+  // std::vector
+  {
+    std::vector<int> x(5);
+    auto aref = MutableArrayRef(x);
+    static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);
+    EXPECT_EQ(aref.data(), x.data());
+    EXPECT_EQ(aref.size(), x.size());
+  }
+
+  // std::array
+  {
+    std::array<int, 5> x{};
+    auto aref = MutableArrayRef(x);
+    static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);
+    EXPECT_EQ(aref.data(), x.data());
+    EXPECT_EQ(aref.size(), x.size());
+  }
+
+  // MutableArrayRef
+  {
+    MutableArrayRef<int> x{};
+    auto aref = MutableArrayRef(x);
+    static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);
+    EXPECT_EQ(aref.data(), x.data());
+    EXPECT_EQ(aref.size(), x.size());
+
+    const MutableArrayRef<int> y{};
+    auto aref2 = MutableArrayRef(y);
+    static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref2)>);
+    EXPECT_EQ(aref2.data(), y.data());
+    EXPECT_EQ(aref2.size(), y.size());
+  }
+
+  // C-style array
+  {
+    int x[] = {0, 1, 2, 3};
+    auto aref = MutableArrayRef(x);
+    static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);
+    EXPECT_EQ(aref.data(), &x[0]);
+    EXPECT_EQ(aref.size(), 4u);
+  }
+}
+
 } // end anonymous namespace