Path: blob/main/contrib/llvm-project/libcxx/include/__algorithm/copy_backward.h
35232 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef _LIBCPP___ALGORITHM_COPY_BACKWARD_H9#define _LIBCPP___ALGORITHM_COPY_BACKWARD_H1011#include <__algorithm/copy_move_common.h>12#include <__algorithm/iterator_operations.h>13#include <__algorithm/min.h>14#include <__config>15#include <__iterator/segmented_iterator.h>16#include <__type_traits/common_type.h>17#include <__type_traits/is_constructible.h>18#include <__utility/move.h>19#include <__utility/pair.h>2021#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)22# pragma GCC system_header23#endif2425_LIBCPP_PUSH_MACROS26#include <__undef_macros>2728_LIBCPP_BEGIN_NAMESPACE_STD2930template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>31_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>32__copy_backward(_InIter __first, _Sent __last, _OutIter __result);3334template <class _AlgPolicy>35struct __copy_backward_impl {36template <class _InIter, class _Sent, class _OutIter>37_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>38operator()(_InIter __first, _Sent __last, _OutIter __result) const {39auto __last_iter = _IterOps<_AlgPolicy>::next(__first, __last);40auto __original_last_iter = __last_iter;4142while (__first != __last_iter) {43*--__result = *--__last_iter;44}4546return std::make_pair(std::move(__original_last_iter), std::move(__result));47}4849template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>50_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>51operator()(_InIter __first, _InIter __last, _OutIter __result) const {52using _Traits = __segmented_iterator_traits<_InIter>;53auto __sfirst = _Traits::__segment(__first);54auto __slast = _Traits::__segment(__last);55if (__sfirst == __slast) {56auto __iters =57std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));58return std::make_pair(__last, __iters.second);59}6061__result =62std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result))63.second;64--__slast;65while (__sfirst != __slast) {66__result =67std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result))68.second;69--__slast;70}71__result = std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result))72.second;73return std::make_pair(__last, std::move(__result));74}7576template <class _InIter,77class _OutIter,78__enable_if_t<__has_random_access_iterator_category<_InIter>::value &&79!__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value,80int> = 0>81_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>82operator()(_InIter __first, _InIter __last, _OutIter __result) const {83using _Traits = __segmented_iterator_traits<_OutIter>;84auto __orig_last = __last;85auto __segment_iterator = _Traits::__segment(__result);8687// When the range contains no elements, __result might not be a valid iterator88if (__first == __last)89return std::make_pair(__first, __result);9091auto __local_last = _Traits::__local(__result);92while (true) {93using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type;9495auto __local_first = _Traits::__begin(__segment_iterator);96auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first);97auto __iter = std::__copy_backward<_AlgPolicy>(__last - __size, __last, __local_last).second;98__last -= __size;99100if (__first == __last)101return std::make_pair(std::move(__orig_last), _Traits::__compose(__segment_iterator, std::move(__iter)));102--__segment_iterator;103__local_last = _Traits::__end(__segment_iterator);104}105}106107// At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.108template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>109_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>110operator()(_In* __first, _In* __last, _Out* __result) const {111return std::__copy_backward_trivial_impl(__first, __last, __result);112}113};114115template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2>116_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2>117__copy_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) {118return std::__copy_move_unwrap_iters<__copy_backward_impl<_AlgPolicy> >(119std::move(__first), std::move(__last), std::move(__result));120}121122template <class _BidirectionalIterator1, class _BidirectionalIterator2>123inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2124copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) {125static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value &&126std::is_copy_constructible<_BidirectionalIterator1>::value,127"Iterators must be copy constructible.");128129return std::__copy_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second;130}131132_LIBCPP_END_NAMESPACE_STD133134_LIBCPP_POP_MACROS135136#endif // _LIBCPP___ALGORITHM_COPY_BACKWARD_H137138139