[libcxx-commits] [libcxx] [libc++] Merge the implementations of ranges::copy_n and std::copy_n and fix vector::insert to assign (PR #157444)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Sep 24 06:40:28 PDT 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/157444
>From df67f593a613e429e6ab04ca6a17fe9b4b054ef2 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 8 Sep 2025 15:05:23 +0200
Subject: [PATCH] [libc++] Merge the implementations of ranges::copy_n and
std::copy_n
---
libcxx/include/__algorithm/copy_n.h | 53 ++++++++++-----------
libcxx/include/__algorithm/ranges_copy_n.h | 30 ++----------
libcxx/include/__iterator/iterator_traits.h | 14 ++++++
libcxx/include/__vector/vector.h | 24 ++--------
4 files changed, 47 insertions(+), 74 deletions(-)
diff --git a/libcxx/include/__algorithm/copy_n.h b/libcxx/include/__algorithm/copy_n.h
index f93f39203a7e3..b81f07fe79567 100644
--- a/libcxx/include/__algorithm/copy_n.h
+++ b/libcxx/include/__algorithm/copy_n.h
@@ -14,47 +14,46 @@
#include <__iterator/iterator_traits.h>
#include <__type_traits/enable_if.h>
#include <__utility/convert_to_integral.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _InputIterator,
- class _Size,
- class _OutputIterator,
- __enable_if_t<__has_input_iterator_category<_InputIterator>::value &&
- !__has_random_access_iterator_category<_InputIterator>::value,
- int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
-copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
- typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
- _IntegralSize __n = __orig_n;
- if (__n > 0) {
+template <class _InIter, class _OutIter, __enable_if_t<__has_random_access_iterator_category<_InIter>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
+__copy_n(_InIter __first, __iter_difference_t<_InIter> __n, _OutIter __result) {
+ return std::__copy(__first, __first + __n, std::move(__result));
+}
+
+template <class _InIter, class _OutIter, __enable_if_t<!__has_random_access_iterator_category<_InIter>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
+__copy_n(_InIter __first, __iter_difference_t<_InIter> __n, _OutIter __result) {
+ while (__n != 0) {
*__result = *__first;
+ ++__first;
++__result;
- for (--__n; __n > 0; --__n) {
- ++__first;
- *__result = *__first;
- ++__result;
- }
+ --__n;
}
- return __result;
+ return std::make_pair(std::move(__first), std::move(__result));
}
-template <class _InputIterator,
- class _Size,
- class _OutputIterator,
- __enable_if_t<__has_random_access_iterator_category<_InputIterator>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
-copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
- typedef typename iterator_traits<_InputIterator>::difference_type difference_type;
- typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
- _IntegralSize __n = __orig_n;
- return std::copy(__first, __first + difference_type(__n), __result);
+template <class _InputIterator, class _Size, class _OutputIterator>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
+copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) {
+ using _IntegralSize = decltype(std::__convert_to_integral(__n));
+ _IntegralSize __converted = __n;
+ return std::__copy_n(__first, __iter_difference_t<_InputIterator>(__converted), __result).second;
}
_LIBCPP_END_NAMESPACE_STD
+_LIBCPP_POP_MACROS
+
#endif // _LIBCPP___ALGORITHM_COPY_N_H
diff --git a/libcxx/include/__algorithm/ranges_copy_n.h b/libcxx/include/__algorithm/ranges_copy_n.h
index 1fbc61674e2dd..3819779701076 100644
--- a/libcxx/include/__algorithm/ranges_copy_n.h
+++ b/libcxx/include/__algorithm/ranges_copy_n.h
@@ -9,16 +9,11 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_COPY_N_H
#define _LIBCPP___ALGORITHM_RANGES_COPY_N_H
-#include <__algorithm/copy.h>
+#include <__algorithm/copy_n.h>
#include <__algorithm/in_out_result.h>
-#include <__algorithm/iterator_operations.h>
-#include <__algorithm/ranges_copy.h>
#include <__config>
-#include <__functional/identity.h>
#include <__iterator/concepts.h>
#include <__iterator/incrementable_traits.h>
-#include <__iterator/unreachable_sentinel.h>
-#include <__iterator/wrap_iter.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -37,32 +32,13 @@ namespace ranges {
template <class _Ip, class _Op>
using copy_n_result = in_out_result<_Ip, _Op>;
-// TODO: Merge this with copy_n
struct __copy_n {
- template <class _InIter, class _DiffType, class _OutIter>
- _LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter>
- __go(_InIter __first, _DiffType __n, _OutIter __result) {
- while (__n != 0) {
- *__result = *__first;
- ++__first;
- ++__result;
- --__n;
- }
- return {std::move(__first), std::move(__result)};
- }
-
- template <random_access_iterator _InIter, class _DiffType, random_access_iterator _OutIter>
- _LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter>
- __go(_InIter __first, _DiffType __n, _OutIter __result) {
- auto __ret = std::__copy(__first, __first + __n, __result);
- return {__ret.first, __ret.second};
- }
-
template <input_iterator _Ip, weakly_incrementable _Op>
requires indirectly_copyable<_Ip, _Op>
_LIBCPP_HIDE_FROM_ABI constexpr copy_n_result<_Ip, _Op>
operator()(_Ip __first, iter_difference_t<_Ip> __n, _Op __result) const {
- return __go(std::move(__first), __n, std::move(__result));
+ auto __res = std::__copy_n(std::move(__first), __n, std::move(__result));
+ return {std::move(__res.first), std::move(__res.second)};
}
};
diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h
index f727e8ff36df2..b5938d58acba8 100644
--- a/libcxx/include/__iterator/iterator_traits.h
+++ b/libcxx/include/__iterator/iterator_traits.h
@@ -473,6 +473,20 @@ using iter_value_t =
indirectly_readable_traits<remove_cvref_t<_Ip> >,
iterator_traits<remove_cvref_t<_Ip> > >::value_type;
+template <class _Iter>
+using __iter_value_t _LIBCPP_NODEBUG = iter_value_t<_Iter>;
+
+template <class _Iter>
+using __iter_difference_t _LIBCPP_NODEBUG = iter_difference_t<_Iter>;
+
+#else
+
+template <class _Iter>
+using __iter_value_t _LIBCPP_NODEBUG = __iter_value_type<_Iter>;
+
+template <class _Iter>
+using __iter_difference_t _LIBCPP_NODEBUG = __iter_diff_t<_Iter>;
+
#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 27e681aeef22a..16e28fd40097b 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -16,7 +16,6 @@
#include <__algorithm/min.h>
#include <__algorithm/move.h>
#include <__algorithm/move_backward.h>
-#include <__algorithm/ranges_copy_n.h>
#include <__algorithm/rotate.h>
#include <__assert>
#include <__config>
@@ -629,8 +628,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__assign_with_size(_Iterator __first, _Sentinel __last, difference_type __n);
- template <class _Iterator,
- __enable_if_t<!is_same<decltype(*std::declval<_Iterator&>())&&, value_type&&>::value, int> = 0>
+ template <class _Iterator, __enable_if_t<!is_same<__iter_value_t<_Iterator>, value_type>::value, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
for (pointer __end_position = __position + __n; __position != __end_position; ++__position, (void)++__first) {
@@ -639,18 +637,10 @@ class vector {
}
}
- template <class _Iterator,
- __enable_if_t<is_same<decltype(*std::declval<_Iterator&>())&&, value_type&&>::value, int> = 0>
+ template <class _Iterator, __enable_if_t<is_same<__iter_value_t<_Iterator>, value_type>::value, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
-#if _LIBCPP_STD_VER >= 23
- if constexpr (!forward_iterator<_Iterator>) { // Handles input-only sized ranges for insert_range
- ranges::copy_n(std::move(__first), __n, __position);
- } else
-#endif
- {
- std::copy_n(__first, __n, __position);
- }
+ std::__copy_n(std::move(__first), __n, __position);
}
template <class _InputIterator, class _Sentinel>
@@ -1084,14 +1074,8 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
size_type __new_size = static_cast<size_type>(__n);
if (__new_size <= capacity()) {
if (__new_size > size()) {
-#if _LIBCPP_STD_VER >= 23
- auto __mid = ranges::copy_n(std::move(__first), size(), this->__begin_).in;
+ auto __mid = std::__copy_n(std::move(__first), size(), this->__begin_).first;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - size());
-#else
- _Iterator __mid = std::next(__first, size());
- std::copy(__first, __mid, this->__begin_);
- __construct_at_end(__mid, __last, __new_size - size());
-#endif
} else {
pointer __m = std::__copy(std::move(__first), __last, this->__begin_).second;
this->__destruct_at_end(__m);
More information about the libcxx-commits
mailing list