diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -372,6 +372,7 @@ __iterator/readable_traits.h __iterator/reverse_access.h __iterator/reverse_iterator.h + __iterator/segmented_iterator.h __iterator/size.h __iterator/sortable.h __iterator/unreachable_sentinel.h diff --git a/libcxx/include/__algorithm/copy.h b/libcxx/include/__algorithm/copy.h --- a/libcxx/include/__algorithm/copy.h +++ b/libcxx/include/__algorithm/copy.h @@ -14,6 +14,7 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> +#include <__iterator/segmented_iterator.h> #include <__utility/move.h> #include <__utility/pair.h> #include @@ -27,6 +28,20 @@ // copy +template ::value + && is_copy_constructible<_Sent>::value + && is_copy_constructible<_OutIter>::value), int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_InIter, _OutIter> __copy(_InIter __first, _Sent __last, _OutIter __result); + +template ::value + && is_copy_constructible<_Sent>::value + && is_copy_constructible<_OutIter>::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +pair<_InIter, _OutIter> __copy(_InIter __first, _Sent __last, _OutIter __result); + template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy_impl(_InIter __first, _Sent __last, _OutIter __result) { @@ -38,6 +53,46 @@ return pair<_InIter, _OutIter>(std::move(__first), std::move(__result)); } +template ::value && + !__segmented_iterator_traits<_InIter>::__is_segmented_iterator::value && + __segmented_iterator_traits<_OutIter>::__is_segmented_iterator::value, + int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> +__copy_impl(_InIter __first, _InIter __last, _OutIter __result) { + if (__first == __last) + return std::make_pair(__last, __result); + + while (true) { + auto __segment = __segmented_iterator_traits<_OutIter>::__get_range_to_segment_end(__result); + auto __segment_size = __segment.__end_ - __segment.__begin_; + auto __range_size = __last - __first; + + if (__range_size < __segment_size) { + auto __iters = std::__copy(__first, __last, __segment.__begin_); + __result += __range_size; + return std::make_pair(__iters.first, __result); + } + + std::__copy(__first, __first + __segment_size, __segment.__begin_); + __first += __segment_size; + __result += __segment_size; + } +} + +template ::__is_segmented_iterator::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> +__copy_impl(_InIter __first, _InIter __last, _OutIter __result) { + for (auto&& __segment : __segmented_iterator_traits<_InIter>::__get_forward_range(__first, __last)) { + auto __iters = std::__copy(__segment.__begin_, __segment.__end_, std::move(__result)); + __result = std::move(__iters.second); + } + return std::make_pair(__last, std::move(__result)); +} + template ::type, _OutValueT>::value @@ -78,7 +133,7 @@ template ::value && is_copy_constructible<_Sent>::value - && is_copy_constructible<_OutIter>::value), int> = 0 > + && is_copy_constructible<_OutIter>::value), int> > inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter __first, _Sent __last, _OutIter __result) { return std::__copy_impl(std::move(__first), std::move(__last), std::move(__result)); @@ -87,7 +142,7 @@ template ::value && is_copy_constructible<_Sent>::value - && is_copy_constructible<_OutIter>::value, int> = 0> + && is_copy_constructible<_OutIter>::value, int> > inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter __first, _Sent __last, _OutIter __result) { auto __range = std::__unwrap_range(__first, __last); diff --git a/libcxx/include/__algorithm/copy_backward.h b/libcxx/include/__algorithm/copy_backward.h --- a/libcxx/include/__algorithm/copy_backward.h +++ b/libcxx/include/__algorithm/copy_backward.h @@ -16,7 +16,9 @@ #include <__concepts/same_as.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__iterator/prev.h> #include <__iterator/reverse_iterator.h> +#include <__iterator/segmented_iterator.h> #include <__ranges/subrange.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -29,8 +31,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template ::value, int> = 0> +template ::value && + !__segmented_iterator_traits<_InputIterator>::__is_segmented_iterator::value && + !__segmented_iterator_traits<_OutputIterator>::__is_segmented_iterator::value, + int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InputIterator, _OutputIterator> __copy_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { auto __ret = std::__copy( @@ -41,7 +48,10 @@ } #if _LIBCPP_STD_VER > 17 -template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI constexpr pair<_Iter1, _Iter2> __copy_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result) { auto __last_iter = _IterOps<_AlgPolicy>::next(__first, std::move(__last)); @@ -51,6 +61,49 @@ } #endif // _LIBCPP_STD_VER > 17 +template ::value && + !__segmented_iterator_traits<_InIter>::__is_segmented_iterator::value && + __segmented_iterator_traits<_OutIter>::__is_segmented_iterator::value, + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> +__copy_backward(_InIter __first, _InIter __last, _OutIter __result) { + if (__first == __last) + return std::make_pair(__last, __result); + + auto __end = __last; + while (true) { + auto __segment = __segmented_iterator_traits<_OutIter>::__get_range_to_segment_begin(__result); + auto __segment_size = __segment.__end_ - __segment.__begin_; + auto __range_size = __last - __first; + + if (__range_size < __segment_size) { + std::__copy_backward<_AlgPolicy>(__first, __last, __segment.__end_); + __result -= __range_size; + return std::make_pair(__end, __result); + } + + std::__copy_backward<_AlgPolicy>(__last - __segment_size, __last, __segment.__end_); + __last -= __segment_size; + __result -= __segment_size; + } +} + +template ::__is_segmented_iterator::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> +__copy_backward(_InIter __first, _InIter __last, _OutIter __result) { + for (auto&& __segment : __segmented_iterator_traits<_InIter>::__get_backward_range(__first, __last)) { + auto __iters = std::__copy_backward<_AlgPolicy>(__segment.__begin_, __segment.__end_, std::move(__result)); + __result = std::move(__iters.second); + } + return std::make_pair(__last, std::move(__result)); +} + template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2 copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) { diff --git a/libcxx/include/__algorithm/move.h b/libcxx/include/__algorithm/move.h --- a/libcxx/include/__algorithm/move.h +++ b/libcxx/include/__algorithm/move.h @@ -11,9 +11,11 @@ #include <__algorithm/iterator_operations.h> #include <__algorithm/unwrap_iter.h> +#include <__algorithm/unwrap_range.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> +#include <__iterator/segmented_iterator.h> #include <__utility/move.h> #include <__utility/pair.h> #include @@ -27,6 +29,20 @@ // move +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +__enable_if_t::value + && is_copy_constructible<_Sent>::value + && is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> > +__move(_InIter __first, _Sent __last, _OutIter __result); + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +__enable_if_t::value + || !is_copy_constructible<_Sent>::value + || !is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> > +__move(_InIter __first, _Sent __last, _OutIter __result); + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { @@ -38,6 +54,46 @@ return std::make_pair(std::move(__first), std::move(__result)); } +template ::value && + !__segmented_iterator_traits<_InIter>::__is_segmented_iterator::value && + __segmented_iterator_traits<_OutIter>::__is_segmented_iterator::value, + int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> +__move_impl(_InIter __first, _InIter __last, _OutIter __result) { + if (__first == __last) + return std::make_pair(__last, __result); + + while (true) { + auto __segment = __segmented_iterator_traits<_OutIter>::__get_range_to_segment_end(__result); + auto __segment_size = __segment.__end_ - __segment.__begin_; + auto __range_size = __last - __first; + + if (__range_size < __segment_size) { + auto __iters = std::__move(__first, __last, __segment.__begin_); + __result += __range_size; + return std::make_pair(__iters.first, __result); + } + + std::__move(__first, __first + __segment_size, __segment.__begin_); + __first += __segment_size; + __result += __segment_size; + } +} + +template ::__is_segmented_iterator::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> +__move_impl(_InIter __first, _InIter __last, _OutIter __result) { + for (auto&& __segment : __segmented_iterator_traits<_InIter>::__get_forward_range(__first, __last)) { + auto __iters = std::__move(__segment.__begin_, __segment.__end_, std::move(__result)); + __result = std::move(__iters.second); + } + return std::make_pair(__last, std::move(__result)); +} + template ::value && is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> > __move(_InIter __first, _Sent __last, _OutIter __result) { + auto __range = std::__unwrap_range(__first, __last); auto __ret = std::__move_impl<_AlgPolicy>( - std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result)); - return std::make_pair(std::__rewrap_iter(__first, __ret.first), std::__rewrap_iter(__result, __ret.second)); + std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__result)); + return std::make_pair(std::__rewrap_range<_Sent>(__first, __ret.first), std::__rewrap_iter(__result, __ret.second)); } template diff --git a/libcxx/include/__algorithm/move_backward.h b/libcxx/include/__algorithm/move_backward.h --- a/libcxx/include/__algorithm/move_backward.h +++ b/libcxx/include/__algorithm/move_backward.h @@ -12,6 +12,7 @@ #include <__algorithm/iterator_operations.h> #include <__algorithm/unwrap_iter.h> #include <__config> +#include <__iterator/segmented_iterator.h> #include <__utility/move.h> #include #include @@ -59,12 +60,14 @@ return __result; } -template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 -_BidirectionalIterator2 -__move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, - _BidirectionalIterator2 __result) -{ +template ::__is_segmented_iterator::value && + !__segmented_iterator_traits<_BidirectionalIterator2>::__is_segmented_iterator::value, + int> = 0> +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2 +__move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) { if (__libcpp_is_constant_evaluated()) { return _VSTD::__move_backward_constexpr<_AlgPolicy>(__first, __last, __result); } else { @@ -75,6 +78,48 @@ } } +template ::value && + !__segmented_iterator_traits<_InIter>::__is_segmented_iterator::value && + __segmented_iterator_traits<_OutIter>::__is_segmented_iterator::value, + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _OutIter +__move_backward(_InIter __first, _InIter __last, _OutIter __result) { + if (__first == __last) + return __result; + + auto __end = __last; + while (true) { + auto __segment = __segmented_iterator_traits<_OutIter>::__get_range_to_segment_begin(__result); + auto __segment_size = __segment.__end_ - __segment.__begin_; + auto __range_size = __last - __first; + + if (__range_size < __segment_size) { + std::__move_backward<_AlgPolicy>(__first, __last, __segment.__end_); + __result -= __range_size; + return __result; + } + + std::__move_backward<_AlgPolicy>(__last - __segment_size, __last, __segment.__end_); + __last -= __segment_size; + __result -= __segment_size; + } +} + +template ::__is_segmented_iterator::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _OutIter +__move_backward(_InIter __first, _InIter __last, _OutIter __result) { + for (auto&& __segment : __segmented_iterator_traits<_InIter>::__get_backward_range(__first, __last)) { + __result = std::__move_backward<_AlgPolicy>(__segment.__begin_, __segment.__end_, std::move(__result)); + } + return std::move(__result); +} + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2 diff --git a/libcxx/include/__iterator/segmented_iterator.h b/libcxx/include/__iterator/segmented_iterator.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__iterator/segmented_iterator.h @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___SEGMENTED_ITERATOR_H +#define _LIBCPP___SEGMENTED_ITERATOR_H + +// segmented iterators are iterators which are made up of multiple other iterators. +// For example, std::deque uses segments to store a few elements in a contiguous block and then have a new block +// after that. To allow algorithms to optimize on this an iterator can specialize __segmented_iterator_traits. +// If __segmented_iterator_traits::__is_segmented_iterator::value is true, the following functions have to be +// implemented: +// - `static __get_forward_range(_Iterator __first, _Iterator __last);` +// where is a range which contains the segments to iterate over. The segments are iterated front to back. +// - `static __get_backward_range(_Iterator __first, _Iterator __last);` +// where is a range which contains the segments to iterate over. The segments are iterated back to front. +// - `static __get_range_to_segment_begin(_Iterator __end)` +// where is a struct where [__begin_, __end_) is a range from begin of the segment to +// the passed-in iterator +// - `static __get_range_to_segment_end(_Iterator __begin)` +// where is a struct where [__begin_, __end_) is a range from the passed-in iterator to +// the end of the segment + +#include <__config> +#include <__type_traits/integral_constant.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __segmented_iterator_traits { + using __is_segmented_iterator = false_type; +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___SEGMENTED_ITERATOR_H diff --git a/libcxx/include/deque b/libcxx/include/deque --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -176,6 +176,7 @@ #include <__iterator/next.h> #include <__iterator/prev.h> #include <__iterator/reverse_iterator.h> +#include <__iterator/segmented_iterator.h> #include <__split_buffer> #include <__utility/forward.h> #include <__utility/move.h> @@ -221,94 +222,6 @@ class _DiffType, _DiffType _BlockSize> class _LIBCPP_TEMPLATE_VIS __deque_iterator; -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type* = 0); - -template -_LIBCPP_HIDE_FROM_ABI _OutputIterator -copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type* = 0); - -template -_LIBCPP_HIDE_FROM_ABI _OutputIterator -copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type* = 0); - -template -_LIBCPP_HIDE_FROM_ABI _OutputIterator -move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type* = 0); - -template -_LIBCPP_HIDE_FROM_ABI _OutputIterator -move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - template struct __deque_block_size { static const _DiffType value = sizeof(_ValueType) < 256 ? 4096 / sizeof(_ValueType) : 16; @@ -336,9 +249,9 @@ static const difference_type __block_size; public: - typedef _ValueType value_type; - typedef random_access_iterator_tag iterator_category; - typedef _Reference reference; + using value_type = _ValueType; + using iterator_category = random_access_iterator_tag; + using reference = _Reference; _LIBCPP_INLINE_VISIBILITY __deque_iterator() _NOEXCEPT #if _LIBCPP_STD_VER > 11 @@ -480,464 +393,151 @@ template friend class _LIBCPP_TEMPLATE_VIS __deque_iterator; - template - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - copy(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*); - - template - friend - _OutputIterator - copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - - template - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - - template - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - copy_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*); - - template - friend - _OutputIterator - copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - - template - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - - template - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - move(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*); - - template - friend - _OutputIterator - move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - - template - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - - template - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - move_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*); - - template - friend - _OutputIterator - move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - - template - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); + template + friend class __deque_range; + + template + friend class __deque_backward_range; + + template + friend struct __segmented_iterator_traits; }; -template -const _DiffType __deque_iterator<_ValueType, _Pointer, _Reference, _MapPointer, - _DiffType, _BlockSize>::__block_size = - __deque_block_size<_ValueType, _DiffType>::value; +template +struct __deque_block_range { + explicit __deque_block_range(_Pointer __b, _Pointer __e) _NOEXCEPT : __begin_(__b), __end_(__e) {} + const _Pointer __begin_; + const _Pointer __end_; +}; -// copy +template +struct __deque_range { + using iterator = _Iterator; + using __deque_block_range = std::__deque_block_range; -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*) -{ - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type; - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::__block_size; - while (__f != __l) - { - pointer __rb = __r.__ptr_; - pointer __re = *__r.__m_iter_ + __block_size; - difference_type __bs = __re - __rb; - difference_type __n = __l - __f; - _RAIter __m = __l; - if (__n > __bs) - { - __n = __bs; - __m = __f + __n; - } - _VSTD::copy(__f, __m, __rb); - __f = __m; - __r += __n; - } - return __r; -} + iterator __pos_; + const iterator __end_; -template -_LIBCPP_HIDE_FROM_ABI _OutputIterator -copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size; - difference_type __n = __l - __f; - while (__n > 0) - { - pointer __fb = __f.__ptr_; - pointer __fe = *__f.__m_iter_ + __block_size; - difference_type __bs = __fe - __fb; - if (__bs > __n) - { - __bs = __n; - __fe = __fb + __bs; - } - __r = _VSTD::copy(__fb, __fe, __r); - __n -= __bs; - __f += __bs; - } - return __r; -} + __deque_range(iterator __pos, iterator __e) _NOEXCEPT + : __pos_(__pos), __end_(__e) {} -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size; - difference_type __n = __l - __f; - while (__n > 0) - { - pointer __fb = __f.__ptr_; - pointer __fe = *__f.__m_iter_ + __block_size; - difference_type __bs = __fe - __fb; - if (__bs > __n) - { - __bs = __n; - __fe = __fb + __bs; - } - __r = _VSTD::copy(__fb, __fe, __r); - __n -= __bs; - __f += __bs; - } - return __r; -} + explicit operator bool() const _NOEXCEPT { + return __pos_ != __end_; + } -// copy_backward + __deque_range begin() const { + return *this; + } -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*) -{ - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type; - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer; - while (__f != __l) - { - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __rp = _VSTD::prev(__r); - pointer __rb = *__rp.__m_iter_; - pointer __re = __rp.__ptr_ + 1; - difference_type __bs = __re - __rb; - difference_type __n = __l - __f; - _RAIter __m = __f; - if (__n > __bs) - { - __n = __bs; - __m = __l - __n; - } - _VSTD::copy_backward(__m, __l, __re); - __l = __m; - __r -= __n; - } - return __r; -} + __deque_range end() const { + return __deque_range(__end_, __end_); + } -template -_LIBCPP_HIDE_FROM_ABI _OutputIterator -copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - difference_type __n = __l - __f; - while (__n > 0) - { - --__l; - pointer __lb = *__l.__m_iter_; - pointer __le = __l.__ptr_ + 1; - difference_type __bs = __le - __lb; - if (__bs > __n) - { - __bs = __n; - __lb = __le - __bs; - } - __r = _VSTD::copy_backward(__lb, __le, __r); - __n -= __bs; - __l -= __bs - 1; + __deque_block_range operator*() const _NOEXCEPT { + if (__pos_.__m_iter_ == __end_.__m_iter_) { + return __deque_block_range(__pos_.__ptr_, __end_.__ptr_); + } else { + return __deque_block_range(__pos_.__ptr_, *__pos_.__m_iter_ + _Iterator::__block_size); } - return __r; -} + } -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - difference_type __n = __l - __f; - while (__n > 0) - { - --__l; - pointer __lb = *__l.__m_iter_; - pointer __le = __l.__ptr_ + 1; - difference_type __bs = __le - __lb; - if (__bs > __n) - { - __bs = __n; - __lb = __le - __bs; - } - __r = _VSTD::copy_backward(__lb, __le, __r); - __n -= __bs; - __l -= __bs - 1; + __deque_range& operator++() _NOEXCEPT { + if (__pos_.__m_iter_ == __end_.__m_iter_) { + __pos_ = __end_; + } else { + ++__pos_.__m_iter_; + __pos_.__ptr_ = *__pos_.__m_iter_; } - return __r; -} + return *this; + } + + _LIBCPP_HIDE_FROM_ABI friend bool operator==(__deque_range const& __lhs, __deque_range const& __rhs) { + return __lhs.__pos_ == __rhs.__pos_; + } + _LIBCPP_HIDE_FROM_ABI friend bool operator!=(__deque_range const& __lhs, __deque_range const& __rhs) { + return !(__lhs == __rhs); + } +}; -// move +template +class __deque_backward_range { + using __deque_block_range = std::__deque_block_range; -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*) -{ - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type; - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::__block_size; - while (__f != __l) - { - pointer __rb = __r.__ptr_; - pointer __re = *__r.__m_iter_ + __block_size; - difference_type __bs = __re - __rb; - difference_type __n = __l - __f; - _RAIter __m = __l; - if (__n > __bs) - { - __n = __bs; - __m = __f + __n; - } - _VSTD::move(__f, __m, __rb); - __f = __m; - __r += __n; - } - return __r; -} + const _Iterator __begin_; + _Iterator __pos_; +public: + _LIBCPP_HIDE_FROM_ABI __deque_backward_range(_Iterator __begin, _Iterator __pos) _NOEXCEPT + : __begin_(__begin), __pos_(__pos) {} -template -_LIBCPP_HIDE_FROM_ABI _OutputIterator -move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size; - difference_type __n = __l - __f; - while (__n > 0) - { - pointer __fb = __f.__ptr_; - pointer __fe = *__f.__m_iter_ + __block_size; - difference_type __bs = __fe - __fb; - if (__bs > __n) - { - __bs = __n; - __fe = __fb + __bs; - } - __r = _VSTD::move(__fb, __fe, __r); - __n -= __bs; - __f += __bs; + _LIBCPP_HIDE_FROM_ABI __deque_backward_range begin() const { + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __deque_backward_range end() const { + return __deque_backward_range(__begin_, __begin_); + } + + _LIBCPP_HIDE_FROM_ABI __deque_block_range operator*() const _NOEXCEPT { + auto __last = std::prev(__pos_); + if (__begin_.__m_iter_ == __last.__m_iter_) { + return __deque_block_range(__begin_.__ptr_, __last.__ptr_ + 1); + } else { + return __deque_block_range(*__last.__m_iter_, __last.__ptr_ + 1); } - return __r; -} + } -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size; - difference_type __n = __l - __f; - while (__n > 0) - { - pointer __fb = __f.__ptr_; - pointer __fe = *__f.__m_iter_ + __block_size; - difference_type __bs = __fe - __fb; - if (__bs > __n) - { - __bs = __n; - __fe = __fb + __bs; - } - __r = _VSTD::move(__fb, __fe, __r); - __n -= __bs; - __f += __bs; + _LIBCPP_HIDE_FROM_ABI __deque_backward_range& operator++() _NOEXCEPT { + --__pos_; + if (__begin_.__m_iter_ == __pos_.__m_iter_) { + __pos_ = __begin_; + } else { + __pos_ -= __pos_.__ptr_ - *__pos_.__m_iter_; } - return __r; -} + return *this; + } -// move_backward + _LIBCPP_HIDE_FROM_ABI friend bool + operator==(const __deque_backward_range& __lhs, const __deque_backward_range& __rhs) { + return __lhs.__pos_ == __rhs.__pos_; + } -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*) -{ - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type; - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer; - while (__f != __l) - { - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __rp = _VSTD::prev(__r); - pointer __rb = *__rp.__m_iter_; - pointer __re = __rp.__ptr_ + 1; - difference_type __bs = __re - __rb; - difference_type __n = __l - __f; - _RAIter __m = __f; - if (__n > __bs) - { - __n = __bs; - __m = __l - __n; - } - _VSTD::move_backward(__m, __l, __re); - __l = __m; - __r -= __n; - } - return __r; -} + _LIBCPP_HIDE_FROM_ABI friend bool + operator!=(const __deque_backward_range& __lhs, const __deque_backward_range& __rhs) { + return !(__lhs == __rhs); + } +}; -template -_LIBCPP_HIDE_FROM_ABI _OutputIterator -move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - difference_type __n = __l - __f; - while (__n > 0) - { - --__l; - pointer __lb = *__l.__m_iter_; - pointer __le = __l.__ptr_ + 1; - difference_type __bs = __le - __lb; - if (__bs > __n) - { - __bs = __n; - __lb = __le - __bs; - } - __r = _VSTD::move_backward(__lb, __le, __r); - __n -= __bs; - __l -= __bs - 1; - } - return __r; -} +template +const _DiffType __deque_iterator<_ValueType, _Pointer, _Reference, _MapPointer, + _DiffType, _BlockSize>::__block_size = + __deque_block_size<_ValueType, _DiffType>::value; -template -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - difference_type __n = __l - __f; - while (__n > 0) - { - --__l; - pointer __lb = *__l.__m_iter_; - pointer __le = __l.__ptr_ + 1; - difference_type __bs = __le - __lb; - if (__bs > __n) - { - __bs = __n; - __lb = __le - __bs; - } - __r = _VSTD::move_backward(__lb, __le, __r); - __n -= __bs; - __l -= __bs - 1; - } - return __r; -} +template +struct __segmented_iterator_traits<__deque_iterator<_V1, _P1, _R1, _M1, _DiffT, _BlockSize> > { + using __is_segmented_iterator = true_type; + using _Iterator = _LIBCPP_NODEBUG __deque_iterator<_V1, _P1, _R1, _M1, _DiffT, _BlockSize>; + using __deque_range = _LIBCPP_NODEBUG std::__deque_range<_Iterator>; + using __deque_backward_range = _LIBCPP_NODEBUG std::__deque_backward_range<_Iterator>; + using __deque_block_range = _LIBCPP_NODEBUG typename __deque_range::__deque_block_range; + + static _LIBCPP_HIDE_FROM_ABI __deque_range __get_forward_range(_Iterator __first, _Iterator __last) { + return __deque_range(__first, __last); + } + + static _LIBCPP_HIDE_FROM_ABI __deque_backward_range __get_backward_range(_Iterator __first, _Iterator __last) { + return __deque_backward_range(__first, __last); + } + + static _LIBCPP_HIDE_FROM_ABI __deque_block_range __get_range_to_segment_begin(_Iterator __end) { + --__end; + return __deque_block_range(*__end.__m_iter_, __end.__ptr_ + 1); + } + + static _LIBCPP_HIDE_FROM_ABI __deque_block_range __get_range_to_segment_end(_Iterator __begin) { + return __deque_block_range(__begin.__ptr_, *__begin.__m_iter_ + _BlockSize); + } +}; template class __deque_base @@ -970,57 +570,8 @@ typedef __deque_iterator const_iterator; - struct __deque_block_range { - explicit __deque_block_range(pointer __b, pointer __e) _NOEXCEPT : __begin_(__b), __end_(__e) {} - const pointer __begin_; - const pointer __end_; - }; - - struct __deque_range { - iterator __pos_; - const iterator __end_; - - __deque_range(iterator __pos, iterator __e) _NOEXCEPT - : __pos_(__pos), __end_(__e) {} - - explicit operator bool() const _NOEXCEPT { - return __pos_ != __end_; - } - - __deque_range begin() const { - return *this; - } - - __deque_range end() const { - return __deque_range(__end_, __end_); - } - __deque_block_range operator*() const _NOEXCEPT { - if (__pos_.__m_iter_ == __end_.__m_iter_) { - return __deque_block_range(__pos_.__ptr_, __end_.__ptr_); - } - return __deque_block_range(__pos_.__ptr_, *__pos_.__m_iter_ + __block_size); - } - - __deque_range& operator++() _NOEXCEPT { - if (__pos_.__m_iter_ == __end_.__m_iter_) { - __pos_ = __end_; - } else { - ++__pos_.__m_iter_; - __pos_.__ptr_ = *__pos_.__m_iter_; - } - return *this; - } - - - _LIBCPP_HIDE_FROM_ABI friend bool operator==(__deque_range const& __lhs, __deque_range const& __rhs) { - return __lhs.__pos_ == __rhs.__pos_; - } - _LIBCPP_HIDE_FROM_ABI friend bool operator!=(__deque_range const& __lhs, __deque_range const& __rhs) { - return !(__lhs == __rhs); - } - }; - - + using __deque_range = std::__deque_range; + using __deque_block_range = typename __deque_range::__deque_block_range; struct _ConstructTransaction { _ConstructTransaction(__deque_base* __db, __deque_block_range& __r) diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp @@ -20,7 +20,9 @@ #include #include #include +#include #include +#include #include "almost_satisfies_types.h" #include "test_iterators.h" @@ -94,20 +96,64 @@ } } -template +template +constexpr void test_containers() { + { + InContainer in {1, 2, 3, 4}; + OutContainer out(4); + std::same_as> auto ret = + std::ranges::copy(In(in.begin()), Sent(In(in.end())), Out(out.begin())); + assert(std::ranges::equal(in, out)); + assert(base(ret.in) == in.end()); + assert(base(ret.out) == out.end()); + } + { + InContainer in {1, 2, 3, 4}; + OutContainer out(4); + auto range = std::ranges::subrange(In(in.begin()), Sent(In(in.end()))); + std::same_as> auto ret = std::ranges::copy(range, Out(out.begin())); + assert(std::ranges::equal(in, out)); + assert(base(ret.in) == in.end()); + assert(base(ret.out) == out.end()); + } +} + +template