[libcxx-commits] [libcxx] [libc++] Fix std::for_each(associative-container) not using std:invoke and projections (PR #171984)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Dec 12 02:25:59 PST 2025
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/171984
None
>From 9bc5354a6311de133af94f7f33046639755864fe Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 12 Dec 2025 11:25:04 +0100
Subject: [PATCH] [libc++] Fix std::for_each(associative-container) not using
std:invoke and projections
---
libcxx/include/__tree | 4 +--
...p => ranges.for_each.associative.pass.cpp} | 25 +++++++++++++++++++
2 files changed, 27 insertions(+), 2 deletions(-)
rename libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/{ranges.for_each.associative.pass copy.cpp => ranges.for_each.associative.pass.cpp} (90%)
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 22aa186470bda..2b93ea6603737 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -670,7 +670,7 @@ bool __tree_iterate_from_root(_Break __break, _NodePtr __root, _Func& __func, _P
}
if (__break(__root))
return true;
- __func(static_cast<_Reference>(__root->__get_value()));
+ std::__invoke(__func, std::__invoke(__proj, static_cast<_Reference>(__root->__get_value())));
if (__root->__right_)
return std::__tree_iterate_from_root<_Reference>(__break, static_cast<_NodePtr>(__root->__right_), __func, __proj);
return false;
@@ -690,7 +690,7 @@ __tree_iterate_subrange(_NodeIter __first_it, _NodeIter __last_it, _Func& __func
if (__first == __last)
return;
const auto __nfirst = static_cast<_NodePtr>(__first);
- __func(static_cast<_Reference>(__nfirst->__get_value()));
+ std::__invoke(__func, std::__invoke(__proj, static_cast<_Reference>(__nfirst->__get_value())));
if (__nfirst->__right_) {
if (std::__tree_iterate_from_root<_Reference>(
[&](_NodePtr __node) -> bool { return __node == __last; },
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.associative.pass copy.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.associative.pass.cpp
similarity index 90%
rename from libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.associative.pass copy.cpp
rename to libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.associative.pass.cpp
index b78adcc461ed1..6c97b1a36f41e 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.associative.pass copy.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.associative.pass.cpp
@@ -156,6 +156,31 @@ void test_node_container(Converter conv) {
assert(invoke_count == 1);
}
}
+
+ { // check that std::invoke is used
+ struct S {
+ int i;
+
+ void zero() {
+ i = 0;
+ }
+ };
+
+ { // Iterator overload
+ std::map<int, S> a = {{1, S{2}}, {3, S{4}}, {5, S{6}}};
+ std::ranges::for_each(a.begin(), a.end(), &S::zero, &std::pair<const int, S>::second);
+ assert(a[1].i == 0);
+ assert(a[3].i == 0);
+ assert(a[5].i == 0);
+ }
+ { // Range overload
+ std::map<int, S> a = {{1, S{2}}, {3, S{4}}, {5, S{6}}};
+ std::ranges::for_each(a, &S::zero, &std::pair<const int, S>::second);
+ assert(a[1].i == 0);
+ assert(a[3].i == 0);
+ assert(a[5].i == 0);
+ }
+ }
}
int main(int, char**) {
More information about the libcxx-commits
mailing list