10
10
#define _LIBCPP___ALGORITHM_COPY_N_H
11
11
12
12
#include < __algorithm/copy.h>
13
+ #include < __algorithm/iterator_operations.h>
13
14
#include < __config>
14
15
#include < __iterator/iterator_traits.h>
15
16
#include < __type_traits/enable_if.h>
16
17
#include < __utility/convert_to_integral.h>
18
+ #include < __utility/move.h>
19
+ #include < __utility/pair.h>
17
20
18
21
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19
22
# pragma GCC system_header
20
23
#endif
21
24
25
+ _LIBCPP_PUSH_MACROS
26
+ #include < __undef_macros>
27
+
22
28
_LIBCPP_BEGIN_NAMESPACE_STD
23
29
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
24
58
template <class _InputIterator ,
25
59
class _Size ,
26
60
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 ) {
35
67
*__result = *__first;
36
68
++__result;
37
- for (--__n; __n > 0 ; --__n ) {
69
+ for (--__converted; __converted > 0 ; --__converted ) {
38
70
++__first;
39
71
*__result = *__first;
40
72
++__result;
@@ -46,15 +78,16 @@ copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
46
78
template <class _InputIterator ,
47
79
class _Size ,
48
80
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, __iter_difference_t <_InputIterator>(__converted), __result).second ;
56
87
}
57
88
58
89
_LIBCPP_END_NAMESPACE_STD
59
90
91
+ _LIBCPP_POP_MACROS
92
+
60
93
#endif // _LIBCPP___ALGORITHM_COPY_N_H
0 commit comments