[libcxx-commits] [libcxx] [libc++] Optimize {std, ranges}::for_each for iterating over __trees (PR #164405)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Dec 2 08:10:27 PST 2025
================
@@ -0,0 +1,131 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <algorithm>
+
+// template<InputIterator Iter, class Function>
+// constexpr Function // constexpr since C++20
+// for_each(Iter first, Iter last, Function f);
+
+#include <algorithm>
+#include <cassert>
+#include <map>
+#include <set>
+
+template <class Container, class Converter>
+void test_node_container(Converter conv) {
+ Container c;
+ using value_type = typename Container::value_type;
+ for (int i = 0; i != 10; ++i)
+ c.insert(conv(i));
+ { // Simple check
+ {
+ int invoke_count = 0;
+ std::ranges::for_each(c.begin(), c.end(), [&c, &invoke_count](const value_type& i) {
+ assert(&i == &*std::next(c.begin(), invoke_count++));
+ });
+ assert(invoke_count == 10);
+ }
+ {
+ int invoke_count = 0;
+ std::ranges::for_each(c, [&c, &invoke_count](const value_type& i) {
+ assert(&i == &*std::next(c.begin(), invoke_count++));
+ });
+ assert(invoke_count == 10);
+ }
+ }
+ { // Make sure that a start within the container works as expected
+ {
+ int invoke_count = 1;
+ std::ranges::for_each(std::next(c.begin()), c.end(), [&c, &invoke_count](const value_type& i) {
+ assert(&i == &*std::next(c.begin(), invoke_count++));
+ });
+ assert(invoke_count == 10);
+ }
+ {
+ int invoke_count = 1;
+ std::ranges::for_each(
+ std::ranges::subrange(std::next(c.begin()), c.end()),
+ [&c, &invoke_count](const value_type& i) { assert(&i == &*std::next(c.begin(), invoke_count++)); });
+ assert(invoke_count == 10);
+ }
+ }
+ { // Make sure that a start within the container works as expected
+ {
+ int invoke_count = 2;
+ std::ranges::for_each(std::next(c.begin(), 2), c.end(), [&c, &invoke_count](const value_type& i) {
+ assert(&i == &*std::next(c.begin(), invoke_count++));
+ });
+ assert(invoke_count == 10);
+ }
+ {
+ int invoke_count = 2;
+ std::ranges::for_each(
+ std::ranges::subrange(std::next(c.begin(), 2), c.end()),
+ [&c, &invoke_count](const value_type& i) { assert(&i == &*std::next(c.begin(), invoke_count++)); });
+ assert(invoke_count == 10);
+ }
+ }
+ { // Make sure that an end within the container works as expected
+ {
+ int invoke_count = 1;
+ std::ranges::for_each(std::next(c.begin()), std::prev(c.end()), [&c, &invoke_count](const value_type& i) {
+ assert(&i == &*std::next(c.begin(), invoke_count++));
+ });
+ assert(invoke_count == 9);
+ }
+ {
+ int invoke_count = 1;
+ std::ranges::for_each(
+ std::ranges::subrange(std::next(c.begin()), std::prev(c.end())),
+ [&c, &invoke_count](const value_type& i) { assert(&i == &*std::next(c.begin(), invoke_count++)); });
+ assert(invoke_count == 9);
+ }
+ }
+ { // Make sure that an empty range works
+ {
+ int invoke_count = 0;
+ std::ranges::for_each(c.begin(), c.begin(), [&c, &invoke_count](const value_type& i) {
----------------
ldionne wrote:
I think we should also test `for_each(c.end(), c.end())`.
https://github.com/llvm/llvm-project/pull/164405
More information about the libcxx-commits
mailing list