[libc++] Merge the segmented iterator code for {copy,move}_backward (#165160)

This removes a bit of code duplication and might simplify future
segmented iterator optimitations.
This commit is contained in:
Nikolas Klauser
2025-12-11 10:32:24 +01:00
committed by GitHub
parent 57cf1ff8d8
commit d15ff5980b
3 changed files with 36 additions and 42 deletions

View File

@@ -11,6 +11,7 @@
#include <__algorithm/copy_move_common.h>
#include <__algorithm/copy_n.h>
#include <__algorithm/for_each_segment.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/min.h>
#include <__config>
@@ -173,27 +174,10 @@ struct __copy_backward_impl {
template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator_v<_InIter>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const {
using _Traits = __segmented_iterator_traits<_InIter>;
auto __sfirst = _Traits::__segment(__first);
auto __slast = _Traits::__segment(__last);
if (__sfirst == __slast) {
auto __iters =
std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));
return std::make_pair(__last, __iters.second);
}
__result =
std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result))
.second;
--__slast;
while (__sfirst != __slast) {
__result =
std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result))
.second;
--__slast;
}
__result = std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result))
.second;
using __local_iterator = typename __segmented_iterator_traits<_InIter>::__local_iterator;
std::__for_each_segment_backward(__first, __last, [&__result](__local_iterator __lfirst, __local_iterator __llast) {
__result = std::__copy_backward<_AlgPolicy>(std::move(__lfirst), std::move(__llast), std::move(__result)).second;
});
return std::make_pair(__last, std::move(__result));
}

View File

@@ -48,6 +48,32 @@ __for_each_segment(_SegmentedIterator __first, _SegmentedIterator __last, _Funct
__func(_Traits::__begin(__sfirst), _Traits::__local(__last));
}
template <class _SegmentedIterator, class _Functor>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
__for_each_segment_backward(_SegmentedIterator __first, _SegmentedIterator __last, _Functor __func) {
using _Traits = __segmented_iterator_traits<_SegmentedIterator>;
auto __sfirst = _Traits::__segment(__first);
auto __slast = _Traits::__segment(__last);
// We are in a single segment, so we might not be at the beginning or end
if (__sfirst == __slast) {
__func(_Traits::__local(__first), _Traits::__local(__last));
return;
}
// We have more than one segment. Iterate over the last segment, since we might not start at the end
__func(_Traits::__begin(__slast), _Traits::__local(__last));
--__slast;
// iterate over the segments which are guaranteed to be completely in the range
while (__sfirst != __slast) {
__func(_Traits::__begin(__slast), _Traits::__end(__slast));
--__slast;
}
// iterate over the first segment
__func(_Traits::__local(__first), _Traits::__end(__slast));
}
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ALGORITHM_FOR_EACH_SEGMENT_H

View File

@@ -11,6 +11,7 @@
#include <__algorithm/copy_backward.h>
#include <__algorithm/copy_move_common.h>
#include <__algorithm/for_each_segment.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/min.h>
#include <__config>
@@ -54,27 +55,10 @@ struct __move_backward_impl {
template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator_v<_InIter>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const {
using _Traits = __segmented_iterator_traits<_InIter>;
auto __sfirst = _Traits::__segment(__first);
auto __slast = _Traits::__segment(__last);
if (__sfirst == __slast) {
auto __iters =
std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));
return std::make_pair(__last, __iters.second);
}
__result =
std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result))
.second;
--__slast;
while (__sfirst != __slast) {
__result =
std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result))
.second;
--__slast;
}
__result = std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result))
.second;
using __local_iterator = typename __segmented_iterator_traits<_InIter>::__local_iterator;
std::__for_each_segment_backward(__first, __last, [&__result](__local_iterator __lfirst, __local_iterator __llast) {
__result = std::__move_backward<_AlgPolicy>(std::move(__lfirst), std::move(__llast), std::move(__result)).second;
});
return std::make_pair(__last, std::move(__result));
}