[llvm] [ADT] Allow member pointers in map_range and map_to_vector (PR #181154)
Jakub Kuderski via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 12 06:40:30 PST 2026
https://github.com/kuhar updated https://github.com/llvm/llvm-project/pull/181154
>From a43a5d27cb88663e96237423fb45657e131f5e78 Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Thu, 12 Feb 2026 09:33:24 -0500
Subject: [PATCH 1/3] [ADT] Allow member pointers in map_range and
map_to_vector
This is for when all we need is to access a field or call a getter:
no need to write a lambda just to extract these.
Assisted-by: claude
---
llvm/include/llvm/ADT/STLExtras.h | 8 ++++++--
llvm/include/llvm/ADT/SmallVectorExtras.h | 2 ++
llvm/unittests/ADT/STLExtrasTest.cpp | 11 +++++++++++
llvm/unittests/ADT/SmallVectorExtrasTest.cpp | 19 +++++++++++++++++++
4 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index 23da931a63de1..8f788f17df920 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -330,7 +330,7 @@ template <typename T> auto drop_end(T &&RangeOrContainer, size_t N = 1) {
template <typename ItTy, typename FuncTy,
typename ReferenceTy =
- decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
+ std::invoke_result_t<FuncTy, decltype(*std::declval<ItTy>())>>
class mapped_iterator
: public iterator_adaptor_base<
mapped_iterator<ItTy, FuncTy>, ItTy,
@@ -347,7 +347,9 @@ class mapped_iterator
const FuncTy &getFunction() const { return F; }
- ReferenceTy operator*() const { return F(*this->I); }
+ ReferenceTy operator*() const {
+ return llvm::invoke(getFunction(), *this->I);
+ }
private:
callable_detail::Callable<FuncTy> F{};
@@ -360,6 +362,8 @@ inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) {
return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F));
}
+/// Return a range that applies \p F to the elements of \p C. \p F can be a
+/// function, lambda, or member pointer.
template <class ContainerTy, class FuncTy>
auto map_range(ContainerTy &&C, FuncTy F) {
return make_range(map_iterator(adl_begin(C), F), map_iterator(adl_end(C), F));
diff --git a/llvm/include/llvm/ADT/SmallVectorExtras.h b/llvm/include/llvm/ADT/SmallVectorExtras.h
index 061293fae0830..2727fdd66e852 100644
--- a/llvm/include/llvm/ADT/SmallVectorExtras.h
+++ b/llvm/include/llvm/ADT/SmallVectorExtras.h
@@ -34,6 +34,7 @@ auto filter_to_vector(ContainerTy &&C, PredicateFn &&Pred) {
}
/// Map a range to a SmallVector with element types deduced from the mapping.
+/// \p F can be a function, lambda, or member pointer.
template <unsigned Size, class ContainerTy, class FuncTy>
auto map_to_vector(ContainerTy &&C, FuncTy &&F) {
return to_vector<Size>(
@@ -41,6 +42,7 @@ auto map_to_vector(ContainerTy &&C, FuncTy &&F) {
}
/// Map a range to a SmallVector with element types deduced from the mapping.
+/// \p F can be a function, lambda, or member pointer.
template <class ContainerTy, class FuncTy>
auto map_to_vector(ContainerTy &&C, FuncTy &&F) {
return to_vector(
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp
index fe71945e4a794..0e72dce216d1f 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -845,6 +845,17 @@ TEST(STLExtrasTest, MapRangeTest) {
some_namespace::some_struct S;
S.data = {3, 4, 5};
EXPECT_THAT(map_range(S, [](int V) { return V * 2; }), ElementsAre(6, 8, 10));
+
+ // Pointer to data member.
+ struct MapRangeStruct {
+ int X;
+ int getX() const { return X; }
+ };
+ std::vector<MapRangeStruct> Structs = {{1}, {2}, {3}};
+ EXPECT_THAT(map_range(Structs, &MapRangeStruct::X), ElementsAre(1, 2, 3));
+
+ // Pointer to member function.
+ EXPECT_THAT(map_range(Structs, &MapRangeStruct::getX), ElementsAre(1, 2, 3));
}
TEST(STLExtrasTest, EarlyIncrementTest) {
diff --git a/llvm/unittests/ADT/SmallVectorExtrasTest.cpp b/llvm/unittests/ADT/SmallVectorExtrasTest.cpp
index 467eb13ac390b..6799015afcc1c 100644
--- a/llvm/unittests/ADT/SmallVectorExtrasTest.cpp
+++ b/llvm/unittests/ADT/SmallVectorExtrasTest.cpp
@@ -22,6 +22,25 @@ using testing::ElementsAre;
namespace llvm {
namespace {
+TEST(SmallVectorExtrasTest, MapToVector) {
+ std::vector<int> Numbers = {1, 2, 3};
+ auto Doubled = map_to_vector(Numbers, [](int X) { return X * 2; });
+ EXPECT_THAT(Doubled, ElementsAre(2, 4, 6));
+
+ // Pointer to data member.
+ struct MapToVectorStruct {
+ int X;
+ int getX() const { return X; }
+ };
+ std::vector<MapToVectorStruct> Structs = {{1}, {2}, {3}};
+ EXPECT_THAT(map_to_vector(Structs, &MapToVectorStruct::X),
+ ElementsAre(1, 2, 3));
+
+ // Pointer to member function.
+ EXPECT_THAT(map_to_vector(Structs, &MapToVectorStruct::getX),
+ ElementsAre(1, 2, 3));
+}
+
TEST(SmallVectorExtrasTest, FilterToVector) {
std::vector<int> Numbers = {0, 1, 2, 3, 4};
auto Odd = filter_to_vector<2>(Numbers, [](int X) { return (X % 2) != 0; });
>From ae4b329d1e7d2e50dd5ccad491a25de7be9a8f26 Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Thu, 12 Feb 2026 09:38:16 -0500
Subject: [PATCH 2/3] Switch to std::invoke since we don't need constexpr
---
llvm/include/llvm/ADT/STLExtras.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index 8f788f17df920..b71e4cd05032c 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -348,7 +348,7 @@ class mapped_iterator
const FuncTy &getFunction() const { return F; }
ReferenceTy operator*() const {
- return llvm::invoke(getFunction(), *this->I);
+ return std::invoke(getFunction(), *this->I);
}
private:
>From 1824cf9b903d3d18e8d9a6f459c83cbd4849c7ef Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Thu, 12 Feb 2026 09:40:18 -0500
Subject: [PATCH 3/3] Simplify
---
llvm/include/llvm/ADT/STLExtras.h | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index b71e4cd05032c..5a21bdd3837be 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -347,9 +347,7 @@ class mapped_iterator
const FuncTy &getFunction() const { return F; }
- ReferenceTy operator*() const {
- return std::invoke(getFunction(), *this->I);
- }
+ ReferenceTy operator*() const { return std::invoke(F, *this->I); }
private:
callable_detail::Callable<FuncTy> F{};
More information about the llvm-commits
mailing list