@@ -472,11 +472,74 @@ class _LIBCPP_TEMPLATE_VIS vector {
472472 this ->__destruct_at_end (this ->__end_ - 1 );
473473 }
474474
475- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert (const_iterator __position, const_reference __x);
475+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert (const_iterator __position, const_reference __x) {
476+ return emplace (std::move (__position), __x);
477+ }
476478
477- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert (const_iterator __position, value_type&& __x);
479+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert (const_iterator __position, value_type&& __x) {
480+ return emplace (std::move (__position), std::move (__x));
481+ }
478482 template <class ... _Args>
479- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator emplace (const_iterator __position, _Args&&... __args);
483+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator emplace (const_iterator __cposition, _Args&&... __args) {
484+ iterator __position = begin () + (__cposition - cbegin ());
485+ if (this ->__end_ < this ->__cap_ ) {
486+ if (__position == end ()) {
487+ allocator_traits<_Allocator>::construct (
488+ this ->__alloc_ , std::__to_address (__position), std::forward<_Args>(__args)...);
489+ ++this ->__end_ ;
490+ } else {
491+ // Construct a temporary value on the stack, so that in case this throws we haven't modified
492+ // the vector yet.
493+ __temporary_emplace_value<value_type> __tmp (this ->__alloc_ , std::forward<_Args>(__args)...);
494+ auto __guard = std::__make_exception_guard ([&] {
495+ allocator_traits<_Allocator>::destroy (this ->__alloc_ , __tmp.__address ());
496+ });
497+
498+ // If the elements are nothrow relocatable, we can relocate them without risking an exception.
499+ // So open up a gap inside the vector, relocate everything to the right and insert the new
500+ // element into the right spot.
501+ //
502+ // Otherwise, we have no choice but to shift everything to the right using move-assignments
503+ // and to move-assign the new element into its final location, to ensure that everything gets
504+ // properly destroyed in case of an exception.
505+ //
506+ // Note that we also require __is_replaceable here for backwards compatibility, because we used
507+ // to perform move-assignments unconditionally. If we didn't enforce that, we would no longer call
508+ // the assignment operator of types that have a funky operator= and expect it to be called in
509+ // vector::insert.
510+ if constexpr (__is_replaceable<value_type>::value && __is_nothrow_allocator_relocatable<_Allocator, value_type>::value) {
511+ // Relocate all the elements in the vector to open up a gap.
512+ std::__uninitialized_allocator_relocate (this ->__alloc_ , __position, end (), __position + 1 );
513+
514+ // Finally, relocate the temporary value into its final location.
515+ std::__allocator_relocate_at (this ->__alloc_ , __tmp.__address (), std::__to_address (__position));
516+ ++this ->__end_ ;
517+ __guard.__complete ();
518+ } else {
519+ // First, move-construct the (new) last element. There is no object at this location, so
520+ // we must use construction.
521+ allocator_traits<_Allocator>::construct (this ->__alloc_ , std::__to_address (end ()), std::move (*(end () - 1 )));
522+ ++this ->__end_ ;
523+
524+ // We now have a moved-from object at `end() - 1`. Shift the rest of the range to the right,
525+ // opening up a gap containing a moved-from object at the insert position.
526+ std::move_backward (__position, end () - 1 , end ());
527+
528+ // Finally, move-assign the new element into its insert position.
529+ *__position = std::move (*__tmp.__address ());
530+ __guard.__complete ();
531+ }
532+ }
533+ __annotate_increase (1 );
534+ return __position;
535+ } else {
536+ __split_buffer<value_type, allocator_type&> __v (__recommend (size () + 1 ), __position - begin (), this ->__alloc_ );
537+ __v.emplace_back (std::forward<_Args>(__args)...);
538+ pointer __p = this ->__begin_ + (__position - begin ());
539+ __p = __swap_out_circular_buffer (__v, __p);
540+ return __make_iter (__p);
541+ }
542+ }
480543
481544 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator
482545 insert (const_iterator __position, size_type __n, const_reference __x);
@@ -1163,68 +1226,6 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
11631226 std::move_backward (__from_s, __from_s + __n, __old_last);
11641227}
11651228
1166- template <class _Tp , class _Allocator >
1167- _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
1168- vector<_Tp, _Allocator>::insert (const_iterator __position, const_reference __x) {
1169- pointer __p = this ->__begin_ + (__position - begin ());
1170- if (this ->__end_ < this ->__cap_ ) {
1171- if (__p == this ->__end_ ) {
1172- __construct_one_at_end (__x);
1173- } else {
1174- __move_range (__p, this ->__end_ , __p + 1 );
1175- const_pointer __xr = pointer_traits<const_pointer>::pointer_to (__x);
1176- if (std::__is_pointer_in_range (std::__to_address (__p), std::__to_address (__end_), std::addressof (__x)))
1177- ++__xr;
1178- *__p = *__xr;
1179- }
1180- } else {
1181- __split_buffer<value_type, allocator_type&> __v (__recommend (size () + 1 ), __p - this ->__begin_ , this ->__alloc_ );
1182- __v.emplace_back (__x);
1183- __p = __swap_out_circular_buffer (__v, __p);
1184- }
1185- return __make_iter (__p);
1186- }
1187-
1188- template <class _Tp , class _Allocator >
1189- _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
1190- vector<_Tp, _Allocator>::insert (const_iterator __position, value_type&& __x) {
1191- pointer __p = this ->__begin_ + (__position - begin ());
1192- if (this ->__end_ < this ->__cap_ ) {
1193- if (__p == this ->__end_ ) {
1194- __construct_one_at_end (std::move (__x));
1195- } else {
1196- __move_range (__p, this ->__end_ , __p + 1 );
1197- *__p = std::move (__x);
1198- }
1199- } else {
1200- __split_buffer<value_type, allocator_type&> __v (__recommend (size () + 1 ), __p - this ->__begin_ , this ->__alloc_ );
1201- __v.emplace_back (std::move (__x));
1202- __p = __swap_out_circular_buffer (__v, __p);
1203- }
1204- return __make_iter (__p);
1205- }
1206-
1207- template <class _Tp , class _Allocator >
1208- template <class ... _Args>
1209- _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
1210- vector<_Tp, _Allocator>::emplace (const_iterator __position, _Args&&... __args) {
1211- pointer __p = this ->__begin_ + (__position - begin ());
1212- if (this ->__end_ < this ->__cap_ ) {
1213- if (__p == this ->__end_ ) {
1214- __construct_one_at_end (std::forward<_Args>(__args)...);
1215- } else {
1216- __temp_value<value_type, _Allocator> __tmp (this ->__alloc_ , std::forward<_Args>(__args)...);
1217- __move_range (__p, this ->__end_ , __p + 1 );
1218- *__p = std::move (__tmp.get ());
1219- }
1220- } else {
1221- __split_buffer<value_type, allocator_type&> __v (__recommend (size () + 1 ), __p - this ->__begin_ , this ->__alloc_ );
1222- __v.emplace_back (std::forward<_Args>(__args)...);
1223- __p = __swap_out_circular_buffer (__v, __p);
1224- }
1225- return __make_iter (__p);
1226- }
1227-
12281229template <class _Tp , class _Allocator >
12291230_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
12301231vector<_Tp, _Allocator>::insert (const_iterator __position, size_type __n, const_reference __x) {
0 commit comments