1414#include < __iterator/iterator_traits.h>
1515#include < __type_traits/enable_if.h>
1616#include < __utility/convert_to_integral.h>
17+ #include < __utility/move.h>
18+ #include < __utility/pair.h>
1719
1820#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1921# pragma GCC system_header
2022#endif
2123
24+ _LIBCPP_PUSH_MACROS
25+ #include < __undef_macros>
26+
2227_LIBCPP_BEGIN_NAMESPACE_STD
2328
29+ template <class _InIter , class _OutIter , __enable_if_t <__has_random_access_iterator_category<_InIter>::value, int > = 0 >
30+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
31+ __copy_n (_InIter __first, __iter_difference_t <_InIter> __n, _OutIter __result) {
32+ return std::__copy (__first, __first + __n, std::move (__result));
33+ }
34+
35+ template <class _InIter , class _OutIter , __enable_if_t <!__has_random_access_iterator_category<_InIter>::value, int > = 0 >
36+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
37+ __copy_n (_InIter __first, __iter_difference_t <_InIter> __n, _OutIter __result) {
38+ while (__n != 0 ) {
39+ *__result = *__first;
40+ ++__first;
41+ ++__result;
42+ --__n;
43+ }
44+ return std::make_pair (std::move (__first), std::move (__result));
45+ }
46+
47+ // The InputIterator case is handled specially here because it's been written in a way to avoid incrementing __first
48+ // if not absolutely required. This was done to allow its use with istream_iterator and we want to avoid breaking
49+ // people, at least currently.
50+ // See https://github.com/llvm/llvm-project/commit/99847d2bf132854fffa019bab19818768102ccad
2451template <class _InputIterator ,
2552 class _Size ,
2653 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;
54+ __enable_if_t <__has_exactly_input_iterator_category<_InputIterator>::value, int > = 0 >
55+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
56+ copy_n (_InputIterator __first, _Size __n, _OutputIterator __result) {
57+ using _IntegralSize = decltype (std::__convert_to_integral (__n));
58+ _IntegralSize __converted = __n;
3459 if (__n > 0 ) {
3560 *__result = *__first;
3661 ++__result;
@@ -46,15 +71,16 @@ copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
4671template <class _InputIterator ,
4772 class _Size ,
4873 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);
74+ __enable_if_t <!__has_exactly_input_iterator_category<_InputIterator>::value, int > = 0 >
75+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
76+ copy_n (_InputIterator __first, _Size __n, _OutputIterator __result) {
77+ using _IntegralSize = decltype (std::__convert_to_integral (__n));
78+ _IntegralSize __converted = __n;
79+ return std::__copy_n (__first, __iter_difference_t <_InputIterator>(__converted), __result).second ;
5680}
5781
5882_LIBCPP_END_NAMESPACE_STD
5983
84+ _LIBCPP_POP_MACROS
85+
6086#endif // _LIBCPP___ALGORITHM_COPY_N_H
0 commit comments