14
14
#include < __iterator/iterator_traits.h>
15
15
#include < __type_traits/enable_if.h>
16
16
#include < __utility/convert_to_integral.h>
17
+ #include < __utility/move.h>
18
+ #include < __utility/pair.h>
17
19
18
20
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19
21
# pragma GCC system_header
20
22
#endif
21
23
24
+ _LIBCPP_PUSH_MACROS
25
+ #include < __undef_macros>
26
+
22
27
_LIBCPP_BEGIN_NAMESPACE_STD
23
28
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
24
51
template <class _InputIterator ,
25
52
class _Size ,
26
53
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;
34
59
if (__n > 0 ) {
35
60
*__result = *__first;
36
61
++__result;
@@ -46,15 +71,16 @@ copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
46
71
template <class _InputIterator ,
47
72
class _Size ,
48
73
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 ;
56
80
}
57
81
58
82
_LIBCPP_END_NAMESPACE_STD
59
83
84
+ _LIBCPP_POP_MACROS
85
+
60
86
#endif // _LIBCPP___ALGORITHM_COPY_N_H
0 commit comments