Skip to content

Commit 1c004a3

Browse files
committed
[libc++] Merge the implementations of ranges::copy_n and std::copy_n
1 parent 8323ff0 commit 1c004a3

File tree

4 files changed

+61
-61
lines changed

4 files changed

+61
-61
lines changed

libcxx/include/__algorithm/copy_n.h

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,48 @@
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
2451
template <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) {
4671
template <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

libcxx/include/__algorithm/ranges_copy_n.h

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,11 @@
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>
14-
#include <__algorithm/iterator_operations.h>
15-
#include <__algorithm/ranges_copy.h>
1614
#include <__config>
17-
#include <__functional/identity.h>
1815
#include <__iterator/concepts.h>
1916
#include <__iterator/incrementable_traits.h>
20-
#include <__iterator/unreachable_sentinel.h>
21-
#include <__iterator/wrap_iter.h>
2217
#include <__utility/move.h>
2318

2419
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -37,32 +32,13 @@ namespace ranges {
3732
template <class _Ip, class _Op>
3833
using copy_n_result = in_out_result<_Ip, _Op>;
3934

40-
// TODO: Merge this with copy_n
4135
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-
6136
template <input_iterator _Ip, weakly_incrementable _Op>
6237
requires indirectly_copyable<_Ip, _Op>
6338
_LIBCPP_HIDE_FROM_ABI constexpr copy_n_result<_Ip, _Op>
6439
operator()(_Ip __first, iter_difference_t<_Ip> __n, _Op __result) const {
65-
return __go(std::move(__first), __n, std::move(__result));
40+
auto __res = std::__copy_n(std::move(__first), __n, std::move(__result));
41+
return {std::move(__res.first), std::move(__res.second)};
6642
}
6743
};
6844

libcxx/include/__iterator/iterator_traits.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,20 @@ using iter_value_t =
473473
indirectly_readable_traits<remove_cvref_t<_Ip> >,
474474
iterator_traits<remove_cvref_t<_Ip> > >::value_type;
475475

476+
template <class _Iter>
477+
using __iter_value_t _LIBCPP_NODEBUG = iter_value_t<_Iter>;
478+
479+
template <class _Iter>
480+
using __iter_difference_t _LIBCPP_NODEBUG = iter_difference_t<_Iter>;
481+
482+
#else
483+
484+
template <class _Iter>
485+
using __iter_value_t _LIBCPP_NODEBUG = __iter_value_type<_Iter>;
486+
487+
template <class _Iter>
488+
using __iter_difference_t _LIBCPP_NODEBUG = __iter_diff_t<_Iter>;
489+
476490
#endif // _LIBCPP_STD_VER >= 20
477491

478492
_LIBCPP_END_NAMESPACE_STD

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>
@@ -629,8 +628,7 @@ class vector {
629628
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
630629
__assign_with_size(_Iterator __first, _Sentinel __last, difference_type __n);
631630

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

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

656646
template <class _InputIterator, class _Sentinel>
@@ -1084,14 +1074,8 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
10841074
size_type __new_size = static_cast<size_type>(__n);
10851075
if (__new_size <= capacity()) {
10861076
if (__new_size > size()) {
1087-
#if _LIBCPP_STD_VER >= 23
1088-
auto __mid = ranges::copy_n(std::move(__first), size(), this->__begin_).in;
1077+
auto __mid = std::__copy_n(std::move(__first), size(), this->__begin_).first;
10891078
__construct_at_end(std::move(__mid), std::move(__last), __new_size - size());
1090-
#else
1091-
_Iterator __mid = std::next(__first, size());
1092-
std::copy(__first, __mid, this->__begin_);
1093-
__construct_at_end(__mid, __last, __new_size - size());
1094-
#endif
10951079
} else {
10961080
pointer __m = std::__copy(std::move(__first), __last, this->__begin_).second;
10971081
this->__destruct_at_end(__m);

0 commit comments

Comments
 (0)