diff options
author | Nikolas Klauser <nikolasklauser@berlin.de> | 2022-07-20 20:24:46 +0200 |
---|---|---|
committer | Nikolas Klauser <nikolasklauser@berlin.de> | 2022-07-20 22:02:14 +0200 |
commit | 23cf42e706fbc2a939ce1470da16599b42258aea (patch) | |
tree | 58b2299d1df9fcb58801b93b719dd9e21ddc1f34 /libcxx/include | |
parent | dc52712a063241bd0d3a0473b4e7ed870e41921f (diff) |
[libc++] Use uninitialized algorithms for vector
Reviewed By: ldionne, #libc
Spies: libcxx-commits, mgorny
Differential Revision: https://reviews.llvm.org/D128146
Diffstat (limited to 'libcxx/include')
-rw-r--r-- | libcxx/include/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libcxx/include/__hash_table | 1 | ||||
-rw-r--r-- | libcxx/include/__memory/swap_allocator.h | 53 | ||||
-rw-r--r-- | libcxx/include/__memory/uninitialized_algorithms.h | 133 | ||||
-rw-r--r-- | libcxx/include/__split_buffer | 1 | ||||
-rw-r--r-- | libcxx/include/__tree | 1 | ||||
-rw-r--r-- | libcxx/include/__utility/transaction.h | 5 | ||||
-rw-r--r-- | libcxx/include/forward_list | 1 | ||||
-rw-r--r-- | libcxx/include/list | 1 | ||||
-rw-r--r-- | libcxx/include/memory | 118 | ||||
-rw-r--r-- | libcxx/include/module.modulemap.in | 1 | ||||
-rw-r--r-- | libcxx/include/string | 1 | ||||
-rw-r--r-- | libcxx/include/vector | 19 |
13 files changed, 212 insertions, 124 deletions
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 71c30e73b5ba..29b693b45509 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -384,6 +384,7 @@ set(files __memory/ranges_uninitialized_algorithms.h __memory/raw_storage_iterator.h __memory/shared_ptr.h + __memory/swap_allocator.h __memory/temporary_buffer.h __memory/uninitialized_algorithms.h __memory/unique_ptr.h diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 6123a310ad63..959ef7fe7d83 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -18,6 +18,7 @@ #include <__debug> #include <__functional/hash.h> #include <__iterator/iterator_traits.h> +#include <__memory/swap_allocator.h> #include <__utility/swap.h> #include <cmath> #include <initializer_list> diff --git a/libcxx/include/__memory/swap_allocator.h b/libcxx/include/__memory/swap_allocator.h new file mode 100644 index 000000000000..64970fa9e2f4 --- /dev/null +++ b/libcxx/include/__memory/swap_allocator.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MEMORY_SWAP_ALLOCATOR_H +#define _LIBCPP___MEMORY_SWAP_ALLOCATOR_H + +#include <__config> +#include <__memory/allocator_traits.h> +#include <__type_traits/integral_constant.h> +#include <__utility/swap.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <typename _Alloc> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void __swap_allocator(_Alloc& __a1, _Alloc& __a2, true_type) +#if _LIBCPP_STD_VER > 11 + _NOEXCEPT +#else + _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) +#endif +{ + using _VSTD::swap; + swap(__a1, __a2); +} + +template <typename _Alloc> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void +__swap_allocator(_Alloc&, _Alloc&, false_type) _NOEXCEPT {} + +template <typename _Alloc> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void __swap_allocator(_Alloc& __a1, _Alloc& __a2) +#if _LIBCPP_STD_VER > 11 + _NOEXCEPT +#else + _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) +#endif +{ + _VSTD::__swap_allocator( + __a1, __a2, integral_constant<bool, allocator_traits<_Alloc>::propagate_on_container_swap::value>()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MEMORY_SWAP_ALLOCATOR_H diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h index 3a8560f080c6..8b8fef1aa597 100644 --- a/libcxx/include/__memory/uninitialized_algorithms.h +++ b/libcxx/include/__memory/uninitialized_algorithms.h @@ -10,12 +10,17 @@ #ifndef _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H #define _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H +#include <__algorithm/copy.h> +#include <__algorithm/move.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__iterator/reverse_iterator.h> #include <__memory/addressof.h> #include <__memory/allocator_traits.h> #include <__memory/construct_at.h> +#include <__memory/pointer_traits.h> #include <__memory/voidify.h> +#include <__type_traits/is_constant_evaluated.h> #include <__utility/move.h> #include <__utility/pair.h> #include <__utility/transaction.h> @@ -347,6 +352,7 @@ uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofir __unreachable_sentinel(), __iter_move); } +// TODO: Rewrite this to iterate left to right and use reverse_iterators when calling // Destroys every element in the range [first, last) FROM RIGHT TO LEFT using allocator // destruction. If elements are themselves C-style arrays, they are recursively destroyed // in the same manner. @@ -492,6 +498,133 @@ constexpr void __uninitialized_allocator_value_construct_n(_Alloc& __alloc, _Bid #endif // _LIBCPP_STD_VER > 14 +// Destroy all elements in [__first, __last) from left to right using allocator destruction. +template <class _Alloc, class _Iter, class _Sent> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void +__allocator_destroy(_Alloc& __alloc, _Iter __first, _Sent __last) { + for (; __first != __last; ++__first) + allocator_traits<_Alloc>::destroy(__alloc, std::__to_address(__first)); +} + +template <class _Alloc, class _Iter> +class _AllocatorDestroyRangeReverse { +public: + _AllocatorDestroyRangeReverse(_Alloc& __alloc, _Iter& __first, _Iter& __last) + : __alloc_(__alloc), __first_(__first), __last_(__last) {} + + _LIBCPP_CONSTEXPR_AFTER_CXX11 void operator()() const { + std::__allocator_destroy(__alloc_, std::reverse_iterator<_Iter>(__last_), std::reverse_iterator<_Iter>(__first_)); + } + +private: + _Alloc& __alloc_; + _Iter& __first_; + _Iter& __last_; +}; + +// Copy-construct [__first1, __last1) in [__first2, __first2 + N), where N is distance(__first1, __last1). +// +// The caller has to ensure that __first2 can hold at least N uninitialized elements. If an exception is thrown the +// already copied elements are destroyed in reverse order of their construction. +template <class _Alloc, class _Iter1, class _Sent1, class _Iter2> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter2 +__uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { + auto __destruct_first = __first2; + auto __guard = + std::__make_transaction(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); + while (__first1 != __last1) { + allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), *__first1); + ++__first1; + ++__first2; + } + __guard.__complete(); + return __first2; +} + +template <class _Alloc, class _Type> +struct __allocator_has_trivial_copy_construct : _Not<__has_construct<_Alloc, _Type*, const _Type&> > {}; + +template <class _Type> +struct __allocator_has_trivial_copy_construct<allocator<_Type>, _Type> : true_type {}; + +template <class _Alloc, + class _Type, + class _RawType = typename remove_const<_Type>::type, + __enable_if_t< + // using _RawType because of the allocator<T const> extension + is_trivially_copy_constructible<_RawType>::value && is_trivially_copy_assignable<_RawType>::value && + __allocator_has_trivial_copy_construct<_Alloc, _RawType>::value>* = nullptr> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Type* +__uninitialized_allocator_copy(_Alloc&, const _Type* __first1, const _Type* __last1, _Type* __first2) { + // TODO: Remove the const_cast once we drop support for std::allocator<T const> + if (__libcpp_is_constant_evaluated()) { + while (__first1 != __last1) { + std::__construct_at(std::__to_address(__first2), *__first1); + ++__first1; + ++__first2; + } + return __first2; + } else { + return std::copy(__first1, __last1, const_cast<_RawType*>(__first2)); + } +} + +// Move-construct the elements [__first1, __last1) into [__first2, __first2 + N) +// if the move constructor is noexcept, where N is distance(__first1, __last1). +// +// Otherwise try to copy all elements. If an exception is thrown the already copied +// elements are destroyed in reverse order of their construction. +template <class _Alloc, class _Iter1, class _Sent1, class _Iter2> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter2 __uninitialized_allocator_move_if_noexcept( + _Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { + static_assert(__is_cpp17_move_insertable<_Alloc>::value, + "The specified type does not meet the requirements of Cpp17MoveInsertable"); + auto __destruct_first = __first2; + auto __guard = + std::__make_transaction(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); + + while (__first1 != __last1) { +#ifndef _LIBCPP_NO_EXCEPTIONS + allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move_if_noexcept(*__first1)); +#else + allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move(*__first1)); +#endif + ++__first1; + ++__first2; + } + __guard.__complete(); + return __first2; +} + +template <class _Alloc, class _Type> +struct __allocator_has_trivial_move_construct : _Not<__has_construct<_Alloc, _Type*, _Type&&> > {}; + +template <class _Type> +struct __allocator_has_trivial_move_construct<allocator<_Type>, _Type> : true_type {}; + +#ifndef _LIBCPP_COMPILER_GCC +template < + class _Alloc, + class _Iter1, + class _Iter2, + class _Type = typename iterator_traits<_Iter1>::value_type, + class = __enable_if_t<is_trivially_move_constructible<_Type>::value && is_trivially_move_assignable<_Type>::value && + __allocator_has_trivial_move_construct<_Alloc, _Type>::value> > +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter1 +__uninitialized_allocator_move_if_noexcept(_Alloc&, _Iter1 __first1, _Iter1 __last1, _Iter2 __first2) { + if (__libcpp_is_constant_evaluated()) { + while (__first1 != __last1) { + std::__construct_at(std::__to_address(__first2), std::move(*__first1)); + ++__first1; + ++__first2; + } + return __first2; + } else { + return std::move(__first1, __last1, __first2); + } +} +#endif // _LIBCPP_COMPILER_GCC + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer index 7409b51b1f96..f78167466217 100644 --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -19,6 +19,7 @@ #include <__iterator/move_iterator.h> #include <__memory/allocator.h> #include <__memory/compressed_pair.h> +#include <__memory/swap_allocator.h> #include <__utility/forward.h> #include <memory> #include <type_traits> diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 8d8449706871..59525a03047a 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -17,6 +17,7 @@ #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> +#include <__memory/swap_allocator.h> #include <__utility/forward.h> #include <__utility/swap.h> #include <limits> diff --git a/libcxx/include/__utility/transaction.h b/libcxx/include/__utility/transaction.h index 87e51c0b198e..e2cc43820845 100644 --- a/libcxx/include/__utility/transaction.h +++ b/libcxx/include/__utility/transaction.h @@ -86,6 +86,11 @@ private: bool __completed_; }; +template <class _Rollback> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __transaction<_Rollback> __make_transaction(_Rollback __rollback) { + return __transaction<_Rollback>(std::move(__rollback)); +} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___UTILITY_TRANSACTION_H diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list index aab3b8715d01..ee90aaa4771f 100644 --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -188,6 +188,7 @@ template <class T, class Allocator, class Predicate> #include <__iterator/iterator_traits.h> #include <__iterator/move_iterator.h> #include <__iterator/next.h> +#include <__memory/swap_allocator.h> #include <__utility/forward.h> #include <limits> #include <memory> diff --git a/libcxx/include/list b/libcxx/include/list index 1db29d14b842..5fcbd67c6703 100644 --- a/libcxx/include/list +++ b/libcxx/include/list @@ -194,6 +194,7 @@ template <class T, class Allocator, class Predicate> #include <__iterator/next.h> #include <__iterator/prev.h> #include <__iterator/reverse_iterator.h> +#include <__memory/swap_allocator.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> diff --git a/libcxx/include/memory b/libcxx/include/memory index ec9f5773929f..56f8159fbd44 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -885,93 +885,6 @@ template<size_t N, class T> _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Alloc, class _Ptr> -_LIBCPP_INLINE_VISIBILITY -void __construct_forward_with_exception_guarantees(_Alloc& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2) { - static_assert(__is_cpp17_move_insertable<_Alloc>::value, - "The specified type does not meet the requirements of Cpp17MoveInsertable"); - typedef allocator_traits<_Alloc> _Traits; - for (; __begin1 != __end1; ++__begin1, (void)++__begin2) { - _Traits::construct(__a, _VSTD::__to_address(__begin2), -#ifdef _LIBCPP_NO_EXCEPTIONS - _VSTD::move(*__begin1) -#else - _VSTD::move_if_noexcept(*__begin1) -#endif - ); - } -} - -template <class _Alloc, class _Tp, typename enable_if< - (__is_default_allocator<_Alloc>::value || !__has_construct<_Alloc, _Tp*, _Tp>::value) && - is_trivially_move_constructible<_Tp>::value ->::type> -_LIBCPP_INLINE_VISIBILITY -void __construct_forward_with_exception_guarantees(_Alloc&, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2) { - ptrdiff_t _Np = __end1 - __begin1; - if (_Np > 0) { - _VSTD::memcpy(__begin2, __begin1, _Np * sizeof(_Tp)); - __begin2 += _Np; - } -} - -template <class _Alloc, class _Iter, class _Ptr> -_LIBCPP_INLINE_VISIBILITY -void __construct_range_forward(_Alloc& __a, _Iter __begin1, _Iter __end1, _Ptr& __begin2) { - typedef allocator_traits<_Alloc> _Traits; - for (; __begin1 != __end1; ++__begin1, (void) ++__begin2) { - _Traits::construct(__a, _VSTD::__to_address(__begin2), *__begin1); - } -} - -template <class _Alloc, class _Source, class _Dest, - class _RawSource = typename remove_const<_Source>::type, - class _RawDest = typename remove_const<_Dest>::type, - class = - typename enable_if< - is_trivially_copy_constructible<_Dest>::value && - is_same<_RawSource, _RawDest>::value && - (__is_default_allocator<_Alloc>::value || !__has_construct<_Alloc, _Dest*, _Source&>::value) - >::type> -_LIBCPP_INLINE_VISIBILITY -void __construct_range_forward(_Alloc&, _Source* __begin1, _Source* __end1, _Dest*& __begin2) { - ptrdiff_t _Np = __end1 - __begin1; - if (_Np > 0) { - _VSTD::memcpy(const_cast<_RawDest*>(__begin2), __begin1, _Np * sizeof(_Dest)); - __begin2 += _Np; - } -} - -template <class _Alloc, class _Ptr> -_LIBCPP_INLINE_VISIBILITY -void __construct_backward_with_exception_guarantees(_Alloc& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2) { - static_assert(__is_cpp17_move_insertable<_Alloc>::value, - "The specified type does not meet the requirements of Cpp17MoveInsertable"); - typedef allocator_traits<_Alloc> _Traits; - while (__end1 != __begin1) { - _Traits::construct(__a, _VSTD::__to_address(__end2 - 1), -#ifdef _LIBCPP_NO_EXCEPTIONS - _VSTD::move(*--__end1) -#else - _VSTD::move_if_noexcept(*--__end1) -#endif - ); - --__end2; - } -} - -template <class _Alloc, class _Tp, class = typename enable_if< - (__is_default_allocator<_Alloc>::value || !__has_construct<_Alloc, _Tp*, _Tp>::value) && - is_trivially_move_constructible<_Tp>::value ->::type> -_LIBCPP_INLINE_VISIBILITY -void __construct_backward_with_exception_guarantees(_Alloc&, _Tp* __begin1, _Tp* __end1, _Tp*& __end2) { - ptrdiff_t _Np = __end1 - __begin1; - __end2 -= _Np; - if (_Np > 0) - _VSTD::memcpy(static_cast<void*>(__end2), static_cast<void const*>(__begin1), _Np * sizeof(_Tp)); -} - struct __destruct_n { private: @@ -1013,37 +926,6 @@ public: _LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space); -// --- Helper for container swap -- -template <typename _Alloc> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -void __swap_allocator(_Alloc & __a1, _Alloc & __a2, true_type) -#if _LIBCPP_STD_VER > 11 - _NOEXCEPT -#else - _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) -#endif -{ - using _VSTD::swap; - swap(__a1, __a2); -} - -template <typename _Alloc> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -void __swap_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {} - -template <typename _Alloc> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -void __swap_allocator(_Alloc & __a1, _Alloc & __a2) -#if _LIBCPP_STD_VER > 11 - _NOEXCEPT -#else - _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) -#endif -{ - _VSTD::__swap_allocator(__a1, __a2, - integral_constant<bool, allocator_traits<_Alloc>::propagate_on_container_swap::value>()); -} - template <typename _Alloc, typename _Traits=allocator_traits<_Alloc> > struct __noexcept_move_assign_container : public integral_constant<bool, _Traits::propagate_on_container_move_assignment::value diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index cbf0b4f7f16d..e2a9dae40a50 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -832,6 +832,7 @@ module std [system] { module ranges_uninitialized_algorithms { private header "__memory/ranges_uninitialized_algorithms.h" } module raw_storage_iterator { private header "__memory/raw_storage_iterator.h" } module shared_ptr { private header "__memory/shared_ptr.h" } + module swap_allocator { private header "__memory/swap_allocator.h" } module temporary_buffer { private header "__memory/temporary_buffer.h" } module uninitialized_algorithms { private header "__memory/uninitialized_algorithms.h" } module unique_ptr { private header "__memory/unique_ptr.h" } diff --git a/libcxx/include/string b/libcxx/include/string index bb169a82c9e7..3723dc8a3938 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -532,6 +532,7 @@ basic_string<char32_t> operator "" s( const char32_t *str, size_t len ); #include <__iterator/reverse_iterator.h> #include <__iterator/wrap_iter.h> #include <__memory/allocate_at_least.h> +#include <__memory/swap_allocator.h> #include <__string/char_traits.h> #include <__string/extern_template_lists.h> #include <__utility/auto_cast.h> diff --git a/libcxx/include/vector b/libcxx/include/vector index 14f586c9bfd7..30030f85e43c 100644 --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -291,6 +291,8 @@ erase_if(vector<T, Allocator>& c, Predicate pred); // C++20 #include <__iterator/reverse_iterator.h> #include <__iterator/wrap_iter.h> #include <__memory/allocate_at_least.h> +#include <__memory/pointer_traits.h> +#include <__memory/swap_allocator.h> #include <__split_buffer> #include <__utility/forward.h> #include <__utility/move.h> @@ -895,9 +897,11 @@ template <class _Tp, class _Allocator> void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v) { - __annotate_delete(); - _VSTD::__construct_backward_with_exception_guarantees(this->__alloc(), this->__begin_, this->__end_, __v.__begin_); + using _RevIter = std::reverse_iterator<pointer>; + __v.__begin_ = std::__uninitialized_allocator_move_if_noexcept( + __alloc(), _RevIter(__end_), _RevIter(__begin_), _RevIter(__v.__begin_)) + .base(); _VSTD::swap(this->__begin_, __v.__begin_); _VSTD::swap(this->__end_, __v.__end_); _VSTD::swap(this->__end_cap(), __v.__end_cap()); @@ -912,8 +916,11 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a { __annotate_delete(); pointer __r = __v.__begin_; - _VSTD::__construct_backward_with_exception_guarantees(this->__alloc(), this->__begin_, __p, __v.__begin_); - _VSTD::__construct_forward_with_exception_guarantees(this->__alloc(), __p, this->__end_, __v.__end_); + using _RevIter = std::reverse_iterator<pointer>; + __v.__begin_ = std::__uninitialized_allocator_move_if_noexcept( + __alloc(), _RevIter(__p), _RevIter(__begin_), _RevIter(__v.__begin_)) + .base(); + __v.__end_ = std::__uninitialized_allocator_move_if_noexcept(__alloc(), __p, __end_, __v.__end_); _VSTD::swap(this->__begin_, __v.__begin_); _VSTD::swap(this->__end_, __v.__end_); _VSTD::swap(this->__end_cap(), __v.__end_cap()); @@ -1001,8 +1008,8 @@ typename enable_if >::type vector<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n) { - _ConstructTransaction __tx(*this, __n); - _VSTD::__construct_range_forward(this->__alloc(), __first, __last, __tx.__pos_); + _ConstructTransaction __tx(*this, __n); + __tx.__pos_ = std::__uninitialized_allocator_copy(__alloc(), __first, __last, __tx.__pos_); } // Default constructs __n objects starting at __end_ |