[llvm] [ArrayRef] Add constructor from iterator_range<U*> (NFC). (PR #137796)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 29 05:23:50 PDT 2025


https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/137796

Add a new constructor to ArrayRef that takes an iterator_range with a random access iterator that can be converted.

This can help to avoid creating unnecessary iterator_ranges for types where an ArrayRef can already be constructed. I will share a follow-up soon.

>From 5f88e72406990afd6d2d9d2546dab227310d18c0 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 29 Apr 2025 13:19:16 +0100
Subject: [PATCH] [ArrayRef] Add constructor from iterator_range<U*> (NFC).

Add a new constructor to ArrayRef that takes an iterator_range with a
random access iterator that can be converted.

This can help to avoid creating unnecessary iterator_ranges for types
where an ArrayRef can already be constructed. I will share a follow-up
soon.
---
 llvm/include/llvm/ADT/ArrayRef.h    | 13 +++++++++++++
 llvm/unittests/ADT/ArrayRefTest.cpp | 20 ++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/llvm/include/llvm/ADT/ArrayRef.h b/llvm/include/llvm/ADT/ArrayRef.h
index a1317423cdd1a..f2fc7b636a8f5 100644
--- a/llvm/include/llvm/ADT/ArrayRef.h
+++ b/llvm/include/llvm/ADT/ArrayRef.h
@@ -149,6 +149,19 @@ namespace llvm {
                  * = nullptr)
         : Data(Vec.data()), Length(Vec.size()) {}
 
+    /// Construct an ArrayRef<T> from iterator_range<U*>. This uses SFINAE
+    /// to ensure that this is only used for iterator ranges of random access
+    /// iterators that can be converted.
+    template <typename U>
+    ArrayRef(const iterator_range<U *> &Range,
+             std::enable_if_t<std::is_base_of<std::random_access_iterator_tag,
+                                              typename std::iterator_traits<
+                                                  decltype(Range.begin())>::
+                                                  iterator_category>::value &&
+                                  std::is_convertible<U *, T const *>::value,
+                              void> * = nullptr)
+        : Data(Range.begin()), Length(llvm::size(Range)) {}
+
     /// @}
     /// @name Simple Operations
     /// @{
diff --git a/llvm/unittests/ADT/ArrayRefTest.cpp b/llvm/unittests/ADT/ArrayRefTest.cpp
index fb25ee19c0b20..128efbea813d2 100644
--- a/llvm/unittests/ADT/ArrayRefTest.cpp
+++ b/llvm/unittests/ADT/ArrayRefTest.cpp
@@ -255,6 +255,26 @@ TEST(ArrayRefTest, ArrayRefFromStdArray) {
   }
 }
 
+TEST(ArrayRefTest, ArrayRefFromIteratorRange) {
+  std::array<int, 5> A1{{42, -5, 0, 1000000, -1000000}};
+  ArrayRef<int> A2 = make_range(A1.begin(), A1.end());
+
+  EXPECT_EQ(A1.size(), A2.size());
+  for (std::size_t i = 0; i < A1.size(); ++i) {
+    EXPECT_EQ(A1[i], A2[i]);
+  }
+}
+
+TEST(ArrayRefTest, ArrayRefFromIteratorConstRange) {
+  std::array<const int, 5> A1{{42, -5, 0, 1000000, -1000000}};
+  ArrayRef<const int> A2 = make_range(A1.begin(), A1.end());
+
+  EXPECT_EQ(A1.size(), A2.size());
+  for (std::size_t i = 0; i < A1.size(); ++i) {
+    EXPECT_EQ(A1[i], A2[i]);
+  }
+}
+
 static_assert(std::is_trivially_copyable_v<ArrayRef<int>>,
               "trivially copyable");
 



More information about the llvm-commits mailing list