Skip to content

Commit 647ea20

Browse files
committed
[libc++] Merge the implementations of ranges::copy_n and std::copy_n
1 parent 70b7874 commit 647ea20

File tree

3 files changed

+56
-62
lines changed

3 files changed

+56
-62
lines changed

libcxx/include/__algorithm/copy_n.h

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,63 @@
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
2458
template <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,16 @@ copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
4678
template <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, __iter_difference_t<_InputIterator>(__converted), __result).second;
5687
}
5788

5889
_LIBCPP_END_NAMESPACE_STD
5990

91+
_LIBCPP_POP_MACROS
92+
6093
#endif // _LIBCPP___ALGORITHM_COPY_N_H

libcxx/include/__algorithm/ranges_copy_n.h

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,12 @@
99
#ifndef _LIBCPP___ALGORITHM_RANGES_COPY_N_H
1010
#define _LIBCPP___ALGORITHM_RANGES_COPY_N_H
1111

12-
#include <__algorithm/copy.h>
12+
#include <__algorithm/copy_n.h>
1313
#include <__algorithm/in_out_result.h>
1414
#include <__algorithm/iterator_operations.h>
15-
#include <__algorithm/ranges_copy.h>
1615
#include <__config>
17-
#include <__functional/identity.h>
1816
#include <__iterator/concepts.h>
1917
#include <__iterator/incrementable_traits.h>
20-
#include <__iterator/unreachable_sentinel.h>
21-
#include <__iterator/wrap_iter.h>
2218
#include <__utility/move.h>
2319

2420
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -37,32 +33,13 @@ namespace ranges {
3733
template <class _Ip, class _Op>
3834
using copy_n_result = in_out_result<_Ip, _Op>;
3935

40-
// TODO: Merge this with copy_n
4136
struct __copy_n {
42-
template <class _InIter, class _DiffType, class _OutIter>
43-
_LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter>
44-
__go(_InIter __first, _DiffType __n, _OutIter __result) {
45-
while (__n != 0) {
46-
*__result = *__first;
47-
++__first;
48-
++__result;
49-
--__n;
50-
}
51-
return {std::move(__first), std::move(__result)};
52-
}
53-
54-
template <random_access_iterator _InIter, class _DiffType, random_access_iterator _OutIter>
55-
_LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter>
56-
__go(_InIter __first, _DiffType __n, _OutIter __result) {
57-
auto __ret = std::__copy(__first, __first + __n, __result);
58-
return {__ret.first, __ret.second};
59-
}
60-
6137
template <input_iterator _Ip, weakly_incrementable _Op>
6238
requires indirectly_copyable<_Ip, _Op>
6339
_LIBCPP_HIDE_FROM_ABI constexpr copy_n_result<_Ip, _Op>
6440
operator()(_Ip __first, iter_difference_t<_Ip> __n, _Op __result) const {
65-
return __go(std::move(__first), __n, std::move(__result));
41+
auto __res = std::__copy_n<_RangeAlgPolicy>(std::move(__first), __n, std::move(__result));
42+
return {std::move(__res.first), std::move(__res.second)};
6643
}
6744
};
6845

libcxx/include/__vector/vector.h

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include <__algorithm/min.h>
1717
#include <__algorithm/move.h>
1818
#include <__algorithm/move_backward.h>
19-
#include <__algorithm/ranges_copy_n.h>
2019
#include <__algorithm/rotate.h>
2120
#include <__assert>
2221
#include <__config>
@@ -628,8 +627,7 @@ class vector {
628627
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
629628
__assign_with_size(_Iterator __first, _Sentinel __last, difference_type __n);
630629

631-
template <class _Iterator,
632-
__enable_if_t<!is_same<decltype(*std::declval<_Iterator&>())&&, value_type&&>::value, int> = 0>
630+
template <class _Iterator, __enable_if_t<!is_same<__iter_value_t<_Iterator>, value_type>::value, int> = 0>
633631
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
634632
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
635633
for (pointer __end_position = __position + __n; __position != __end_position; ++__position, (void)++__first) {
@@ -638,18 +636,10 @@ class vector {
638636
}
639637
}
640638

641-
template <class _Iterator,
642-
__enable_if_t<is_same<decltype(*std::declval<_Iterator&>())&&, value_type&&>::value, int> = 0>
639+
template <class _Iterator, __enable_if_t<is_same<__iter_value_t<_Iterator>, value_type>::value, int> = 0>
643640
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
644641
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
645-
#if _LIBCPP_STD_VER >= 23
646-
if constexpr (!forward_iterator<_Iterator>) { // Handles input-only sized ranges for insert_range
647-
ranges::copy_n(std::move(__first), __n, __position);
648-
} else
649-
#endif
650-
{
651-
std::copy_n(__first, __n, __position);
652-
}
642+
std::__copy_n(std::move(__first), __n, __position);
653643
}
654644

655645
template <class _InputIterator, class _Sentinel>
@@ -1083,14 +1073,8 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
10831073
size_type __new_size = static_cast<size_type>(__n);
10841074
if (__new_size <= capacity()) {
10851075
if (__new_size > size()) {
1086-
#if _LIBCPP_STD_VER >= 23
1087-
auto __mid = ranges::copy_n(std::move(__first), size(), this->__begin_).in;
1076+
auto __mid = std::__copy_n(std::move(__first), size(), this->__begin_).first;
10881077
__construct_at_end(std::move(__mid), std::move(__last), __new_size - size());
1089-
#else
1090-
_Iterator __mid = std::next(__first, size());
1091-
std::copy(__first, __mid, this->__begin_);
1092-
__construct_at_end(__mid, __last, __new_size - size());
1093-
#endif
10941078
} else {
10951079
pointer __m = std::__copy(std::move(__first), __last, this->__begin_).second;
10961080
this->__destruct_at_end(__m);

0 commit comments

Comments
 (0)