Skip to content

Commit 1cdf3c6

Browse files
committed
Backport for_each segmented iterator optimization to C++03
1 parent 76d7227 commit 1cdf3c6

File tree

1 file changed

+32
-17
lines changed

1 file changed

+32
-17
lines changed

libcxx/include/__algorithm/for_each.h

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <__algorithm/for_each_segment.h>
1414
#include <__config>
1515
#include <__iterator/segmented_iterator.h>
16-
#include <__ranges/movable_box.h>
16+
#include <__type_traits/enable_if.h>
1717
#include <__utility/in_place.h>
1818
#include <__utility/move.h>
1919

@@ -26,28 +26,43 @@ _LIBCPP_PUSH_MACROS
2626

2727
_LIBCPP_BEGIN_NAMESPACE_STD
2828

29-
template <class _InputIterator, class _Function>
30-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function
31-
for_each(_InputIterator __first, _InputIterator __last, _Function __f) {
29+
template <class _InputIterator, class _Sent, class _Func>
30+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __for_each(_InputIterator __first, _Sent __last, _Func& __f) {
3231
for (; __first != __last; ++__first)
3332
__f(*__first);
34-
return __f;
3533
}
3634

37-
// __movable_box is available in C++20, but is actually a copyable-box, so optimization is only correct in C++23
38-
#if _LIBCPP_STD_VER >= 23
39-
template <class _SegmentedIterator, class _Function>
40-
requires __is_segmented_iterator<_SegmentedIterator>::value
35+
// __segment_processor handles the per-segment processing by applying the function object __func_ to each
36+
// element within the segment.
37+
template <class _SegmentedIterator, class _Func>
38+
struct __segment_processor {
39+
using _Traits _LIBCPP_NODEBUG = __segmented_iterator_traits<_SegmentedIterator>;
40+
41+
_Func& __func_;
42+
43+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __segment_processor(_Func& __f) : __func_(__f) {}
44+
45+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
46+
operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) {
47+
std::__for_each(__lfirst, __llast, __func_);
48+
}
49+
};
50+
51+
template <class _SegmentedIterator,
52+
class _Function,
53+
__enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0>
4154
_LIBCPP_HIDE_FROM_ABI constexpr _Function
42-
for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Function __func) {
43-
ranges::__movable_box<_Function> __wrapped_func(in_place, std::move(__func));
44-
std::__for_each_segment(__first, __last, [&](auto __lfirst, auto __llast) {
45-
__wrapped_func =
46-
ranges::__movable_box<_Function>(in_place, std::for_each(__lfirst, __llast, std::move(*__wrapped_func)));
47-
});
48-
return std::move(*__wrapped_func);
55+
__for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Function __func) {
56+
std::__for_each_segment(__first, __last, std::__segment_processor<_SegmentedIterator, _Function>(__func));
57+
return __func;
58+
}
59+
60+
template <class _InputIterator, class _Function>
61+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function
62+
for_each(_InputIterator __first, _InputIterator __last, _Function __f) {
63+
std::__for_each(__first, __last, __f);
64+
return __f;
4965
}
50-
#endif // _LIBCPP_STD_VER >= 23
5166

5267
_LIBCPP_END_NAMESPACE_STD
5368

0 commit comments

Comments
 (0)