1515#include < __algorithm/min.h>
1616#include < __algorithm/move.h>
1717#include < __algorithm/move_backward.h>
18+ #include < __algorithm/ranges_copy_n.h>
1819#include < __algorithm/rotate.h>
1920#include < __assert>
2021#include < __config>
2324#include < __fwd/vector.h>
2425#include < __iterator/advance.h>
2526#include < __iterator/bounded_iter.h>
27+ #include < __iterator/concepts.h>
2628#include < __iterator/distance.h>
2729#include < __iterator/iterator_traits.h>
2830#include < __iterator/move_iterator.h>
5456#include < __type_traits/is_same.h>
5557#include < __type_traits/is_trivially_relocatable.h>
5658#include < __type_traits/type_identity.h>
59+ #include < __utility/declval.h>
5760#include < __utility/exception_guard.h>
5861#include < __utility/forward.h>
5962#include < __utility/is_pointer_in_range.h>
@@ -570,7 +573,7 @@ class _LIBCPP_TEMPLATE_VIS vector {
570573
571574 if (__n > 0 ) {
572575 __vallocate (__n);
573- __construct_at_end (__first, __last, __n);
576+ __construct_at_end (std::move ( __first), std::move ( __last) , __n);
574577 }
575578
576579 __guard.__complete ();
@@ -590,9 +593,31 @@ class _LIBCPP_TEMPLATE_VIS vector {
590593 template <class _Iterator , class _Sentinel >
591594 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel (_Iterator __first, _Sentinel __last);
592595
593- template <class _ForwardIterator , class _Sentinel >
596+ // The `_Iterator` in `*_with_size` functions can be input-only only if called from `*_range` (since C++23).
597+ // Otherwise, `_Iterator` is a forward iterator.
598+
599+ template <class _Iterator , class _Sentinel >
600+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
601+ __assign_with_size (_Iterator __first, _Sentinel __last, difference_type __n);
602+
603+ template <class _Iterator ,
604+ __enable_if_t <!is_same<decltype (*std::declval<_Iterator&>())&&, value_type&&>::value, int > = 0 >
605+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
606+ __insert_assign_n_unchecked (_Iterator __first, difference_type __n, pointer __position) {
607+ for (pointer __end_position = __position + __n; __position != __end_position; (void )++__position, ++__first) {
608+ __temp_value<value_type, _Allocator> __tmp (this ->__alloc (), *__first);
609+ *__position = std::move (__tmp.get ());
610+ }
611+ }
612+
613+ template <class _Iterator ,
614+ __enable_if_t <is_same<decltype (*std::declval<_Iterator&>())&&, value_type&&>::value, int > = 0 >
594615 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
595- __assign_with_size (_ForwardIterator __first, _Sentinel __last, difference_type __n);
616+ __insert_assign_n_unchecked (_Iterator __first, difference_type __n, pointer __position) {
617+ for (pointer __end_position = __position + __n; __position != __end_position; (void )++__position, ++__first) {
618+ *__position = *__first;
619+ }
620+ }
596621
597622 template <class _InputIterator , class _Sentinel >
598623 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator
@@ -916,7 +941,7 @@ template <class _InputIterator, class _Sentinel>
916941_LIBCPP_CONSTEXPR_SINCE_CXX20 void
917942vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
918943 _ConstructTransaction __tx (*this , __n);
919- __tx.__pos_ = std::__uninitialized_allocator_copy (__alloc (), __first, __last, __tx.__pos_ );
944+ __tx.__pos_ = std::__uninitialized_allocator_copy (__alloc (), std::move ( __first), std::move ( __last) , __tx.__pos_ );
920945}
921946
922947// Default constructs __n objects starting at __end_
@@ -1023,23 +1048,31 @@ vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __l
10231048}
10241049
10251050template <class _Tp , class _Allocator >
1026- template <class _ForwardIterator , class _Sentinel >
1051+ template <class _Iterator , class _Sentinel >
10271052_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
1028- vector<_Tp, _Allocator>::__assign_with_size(_ForwardIterator __first, _Sentinel __last, difference_type __n) {
1053+ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last, difference_type __n) {
10291054 size_type __new_size = static_cast <size_type>(__n);
10301055 if (__new_size <= capacity ()) {
10311056 if (__new_size > size ()) {
1032- _ForwardIterator __mid = std::next (__first, size ());
1033- std::copy (__first, __mid, this ->__begin_ );
1034- __construct_at_end (__mid, __last, __new_size - size ());
1057+ #if _LIBCPP_STD_VER >= 23
1058+ if constexpr (!forward_iterator<_Iterator>) {
1059+ auto __mid = ranges::copy_n (std::move (__first), size (), this ->__begin_ ).in ;
1060+ __construct_at_end (std::move (__mid), std::move (__last), __new_size - size ());
1061+ } else
1062+ #endif
1063+ {
1064+ _Iterator __mid = std::next (__first, size ());
1065+ std::copy (__first, __mid, this ->__begin_ );
1066+ __construct_at_end (__mid, __last, __new_size - size ());
1067+ }
10351068 } else {
1036- pointer __m = std::__copy (__first, __last, this ->__begin_ ).second ;
1069+ pointer __m = std::__copy (std::move ( __first) , __last, this ->__begin_ ).second ;
10371070 this ->__destruct_at_end (__m);
10381071 }
10391072 } else {
10401073 __vdeallocate ();
10411074 __vallocate (__recommend (__new_size));
1042- __construct_at_end (__first, __last, __new_size);
1075+ __construct_at_end (std::move ( __first), std::move ( __last) , __new_size);
10431076 }
10441077}
10451078
@@ -1297,29 +1330,34 @@ template <class _Iterator, class _Sentinel>
12971330_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
12981331vector<_Tp, _Allocator>::__insert_with_size (
12991332 const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n) {
1300- auto __insertion_size = __n;
1301- pointer __p = this ->__begin_ + (__position - begin ());
1333+ pointer __p = this ->__begin_ + (__position - begin ());
13021334 if (__n > 0 ) {
13031335 if (__n <= this ->__end_cap () - this ->__end_ ) {
1304- size_type __old_n = __n;
13051336 pointer __old_last = this ->__end_ ;
1306- _Iterator __m = std::next (__first, __n);
13071337 difference_type __dx = this ->__end_ - __p;
13081338 if (__n > __dx) {
1309- __m = __first;
1310- difference_type __diff = this ->__end_ - __p;
1311- std::advance (__m, __diff);
1312- __construct_at_end (__m, __last, __n - __diff);
1313- __n = __dx;
1314- }
1315- if (__n > 0 ) {
1316- __move_range (__p, __old_last, __p + __old_n);
1317- std::copy (__first, __m, __p);
1339+ #if _LIBCPP_STD_VER >= 23
1340+ if constexpr (!forward_iterator<_Iterator>) {
1341+ __construct_at_end (std::move (__first), std::move (__last), __n);
1342+ std::rotate (__p, __old_last, this ->__end_ );
1343+ } else
1344+ #endif
1345+ {
1346+ _Iterator __m = std::next (__first, __dx);
1347+ __construct_at_end (__m, __last, __n - __dx);
1348+ if (__dx > 0 ) {
1349+ __move_range (__p, __old_last, __p + __n);
1350+ __insert_assign_n_unchecked (__first, __dx, __p);
1351+ }
1352+ }
1353+ } else {
1354+ __move_range (__p, __old_last, __p + __n);
1355+ __insert_assign_n_unchecked (std::move (__first), __n, __p);
13181356 }
13191357 } else {
13201358 allocator_type& __a = this ->__alloc ();
13211359 __split_buffer<value_type, allocator_type&> __v (__recommend (size () + __n), __p - this ->__begin_ , __a);
1322- __v.__construct_at_end_with_size (__first, __insertion_size );
1360+ __v.__construct_at_end_with_size (std::move ( __first), __n );
13231361 __p = __swap_out_circular_buffer (__v, __p);
13241362 }
13251363 }
0 commit comments