[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 09:44:14 PDT 2025
https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/137796
>From 85b5450560aa4d2fed83760727757165f5832dc9 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 1/3] [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");
>From 2dcafd439dd038b793a340c39cdff7364d1801ca Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 29 Apr 2025 17:40:23 +0100
Subject: [PATCH 2/3] !fixup address latest comments, thanks!
---
llvm/include/llvm/ADT/ArrayRef.h | 17 +++++++++--------
llvm/unittests/ADT/ArrayRefTest.cpp | 6 ++----
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/llvm/include/llvm/ADT/ArrayRef.h b/llvm/include/llvm/ADT/ArrayRef.h
index f2fc7b636a8f5..47ba9fe3a23e3 100644
--- a/llvm/include/llvm/ADT/ArrayRef.h
+++ b/llvm/include/llvm/ADT/ArrayRef.h
@@ -152,14 +152,15 @@ namespace llvm {
/// 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)
+ template <typename U,
+ typename = std::enable_if_t<
+ std::is_base_of<
+ std::random_access_iterator_tag,
+ typename std::iterator_traits<
+ decltype(std::declval<const iterator_range<U *> &>()
+ .begin())>::iterator_category>::value &&
+ std::is_convertible_v<U *, T const *>>>
+ ArrayRef(const iterator_range<U *> &Range)
: Data(Range.begin()), Length(llvm::size(Range)) {}
/// @}
diff --git a/llvm/unittests/ADT/ArrayRefTest.cpp b/llvm/unittests/ADT/ArrayRefTest.cpp
index 128efbea813d2..098a0910b6cb8 100644
--- a/llvm/unittests/ADT/ArrayRefTest.cpp
+++ b/llvm/unittests/ADT/ArrayRefTest.cpp
@@ -260,9 +260,8 @@ TEST(ArrayRefTest, ArrayRefFromIteratorRange) {
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) {
+ for (std::size_t i = 0; i < A1.size(); ++i)
EXPECT_EQ(A1[i], A2[i]);
- }
}
TEST(ArrayRefTest, ArrayRefFromIteratorConstRange) {
@@ -270,9 +269,8 @@ TEST(ArrayRefTest, ArrayRefFromIteratorConstRange) {
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) {
+ 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>>,
>From bdb308073db1d4ff4a42939c1111176dcc258fef Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 29 Apr 2025 17:43:40 +0100
Subject: [PATCH 3/3] !fixup enable_if
---
llvm/include/llvm/ADT/ArrayRef.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/ADT/ArrayRef.h b/llvm/include/llvm/ADT/ArrayRef.h
index 47ba9fe3a23e3..c380f71832d13 100644
--- a/llvm/include/llvm/ADT/ArrayRef.h
+++ b/llvm/include/llvm/ADT/ArrayRef.h
@@ -153,7 +153,7 @@ namespace llvm {
/// to ensure that this is only used for iterator ranges of random access
/// iterators that can be converted.
template <typename U,
- typename = std::enable_if_t<
+ typename = std::enable_if<
std::is_base_of<
std::random_access_iterator_tag,
typename std::iterator_traits<
More information about the llvm-commits
mailing list