1010#define _LIBCPP___ALGORITHM_COPY_N_H
1111
1212#include < __algorithm/copy.h>
13+ #include < __algorithm/iterator_operations.h>
1314#include < __config>
1415#include < __iterator/iterator_traits.h>
1516#include < __type_traits/enable_if.h>
1617#include < __utility/convert_to_integral.h>
18+ #include < __utility/move.h>
19+ #include < __utility/pair.h>
1720
1821#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1922# pragma GCC system_header
2023#endif
2124
25+ _LIBCPP_PUSH_MACROS
26+ #include < __undef_macros>
27+
2228_LIBCPP_BEGIN_NAMESPACE_STD
2329
30+ template <class _AlgPolicy ,
31+ class _InIter ,
32+ class _OutIter ,
33+ __enable_if_t <__has_random_access_iterator_category<_InIter>::value, int > = 0 >
34+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
35+ __copy_n (_InIter __first, typename _IterOps<_AlgPolicy>::template __difference_type<_InIter> __n, _OutIter __result) {
36+ return std::__copy (__first, __first + __n, std::move (__result));
37+ }
38+
39+ template <class _AlgPolicy ,
40+ class _InIter ,
41+ class _OutIter ,
42+ __enable_if_t <!__has_random_access_iterator_category<_InIter>::value, int > = 0 >
43+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
44+ __copy_n (_InIter __first, typename _IterOps<_AlgPolicy>::template __difference_type<_InIter> __n, _OutIter __result) {
45+ while (__n != 0 ) {
46+ *__result = *__first;
47+ ++__first;
48+ ++__result;
49+ --__n;
50+ }
51+ return std::make_pair (std::move (__first), std::move (__result));
52+ }
53+
54+ // The InputIterator case is handled specially here because it's been written in a way to avoid incrementing __first
55+ // if not absolutely required. This was done to allow its use with istream_iterator and we want to avoid breaking
56+ // people, at least currently.
57+ // See https://github.com/llvm/llvm-project/commit/99847d2bf132854fffa019bab19818768102ccad
2458template <class _InputIterator ,
2559 class _Size ,
2660 class _OutputIterator ,
27- __enable_if_t <__has_input_iterator_category<_InputIterator>::value &&
28- !__has_random_access_iterator_category<_InputIterator>::value,
29- int > = 0 >
30- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
31- copy_n (_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
32- typedef decltype (std::__convert_to_integral (__orig_n)) _IntegralSize;
33- _IntegralSize __n = __orig_n;
34- if (__n > 0 ) {
61+ __enable_if_t <__has_exactly_input_iterator_category<_InputIterator>::value, int > = 0 >
62+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
63+ copy_n (_InputIterator __first, _Size __n, _OutputIterator __result) {
64+ using _IntegralSize = decltype (std::__convert_to_integral (__n));
65+ _IntegralSize __converted = __n;
66+ if (__converted > 0 ) {
3567 *__result = *__first;
3668 ++__result;
37- for (--__n; __n > 0 ; --__n ) {
69+ for (--__converted; __converted > 0 ; --__converted ) {
3870 ++__first;
3971 *__result = *__first;
4072 ++__result;
@@ -46,15 +78,17 @@ copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
4678template <class _InputIterator ,
4779 class _Size ,
4880 class _OutputIterator ,
49- __enable_if_t <__has_random_access_iterator_category <_InputIterator>::value, int > = 0 >
50- inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
51- copy_n (_InputIterator __first, _Size __orig_n , _OutputIterator __result) {
52- typedef typename iterator_traits<_InputIterator>::difference_type difference_type ;
53- typedef decltype ( std::__convert_to_integral (__orig_n)) _IntegralSize ;
54- _IntegralSize __n = __orig_n;
55- return std::copy (__first, __first + difference_type (__n), __result) ;
81+ __enable_if_t <!__has_exactly_input_iterator_category <_InputIterator>::value, int > = 0 >
82+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
83+ copy_n (_InputIterator __first, _Size __n , _OutputIterator __result) {
84+ using _IntegralSize = decltype ( std::__convert_to_integral (__n)) ;
85+ _IntegralSize __converted = __n ;
86+ return std::__copy_n<_ClassicAlgPolicy>(__first, __iterator_difference_type<_InputIterator>(__converted), __result)
87+ . second ;
5688}
5789
5890_LIBCPP_END_NAMESPACE_STD
5991
92+ _LIBCPP_POP_MACROS
93+
6094#endif // _LIBCPP___ALGORITHM_COPY_N_H
0 commit comments