diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst index 0fd7e53aed158..9274da55fccf8 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -74,6 +74,8 @@ Improvements and New Features - The ``std::{fill, fill_n}`` and ``std::ranges::{fill, fill_n}`` algorithms have been optimized for segmented iterators, resulting in a performance improvement of at least 10x for ``std::deque`` iterators and ``std::join_view>>`` iterators. +- The ``std::generate`` algorithm has been optimized for segmented iterators, resulting in a performance improvement for + ``std::deque`` and ``std::join_view>>`` iterators. Deprecations and Removals ------------------------- diff --git a/libcxx/include/__algorithm/generate.h b/libcxx/include/__algorithm/generate.h index c95b527402f5d..c4cd75cd0a4d6 100644 --- a/libcxx/include/__algorithm/generate.h +++ b/libcxx/include/__algorithm/generate.h @@ -9,7 +9,9 @@ #ifndef _LIBCPP___ALGORITHM_GENERATE_H #define _LIBCPP___ALGORITHM_GENERATE_H +#include <__algorithm/for_each.h> #include <__config> +#include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,8 +22,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) { - for (; __first != __last; ++__first) - *__first = __gen(); + using __iter_ref = decltype(*__first); + std::for_each(__first, __last, [&](__iter_ref __element) { std::forward<__iter_ref>(__element) = __gen(); }); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate.pass.cpp index 29d32d7156742..4591d7ece4645 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate.pass.cpp @@ -16,6 +16,7 @@ #include #include +#include #include "test_macros.h" #include "test_iterators.h" @@ -51,12 +52,22 @@ test() assert(ia[3] == 1); } +void deque_test() { + int sizes[] = {0, 1, 2, 1023, 1024, 1025, 2047, 2048, 2049}; + for (const int size : sizes) { + std::deque d(size); + std::generate(d.begin(), d.end(), gen_test()); + assert(std::all_of(d.begin(), d.end(), [](int x) { return x == 1; })); + } +} + int main(int, char**) { test >(); test >(); test >(); test(); + deque_test(); #if TEST_STD_VER > 17 static_assert(test_constexpr());