1fe6060f1SDimitry Andric // -*- C++ -*- 2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 3fe6060f1SDimitry Andric // 4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7fe6060f1SDimitry Andric // 8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 9fe6060f1SDimitry Andric 10fe6060f1SDimitry Andric #ifndef _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H 11fe6060f1SDimitry Andric #define _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H 12fe6060f1SDimitry Andric 13972a253aSDimitry Andric #include <__algorithm/copy.h> 14972a253aSDimitry Andric #include <__algorithm/move.h> 1506c3fb27SDimitry Andric #include <__algorithm/unwrap_iter.h> 1606c3fb27SDimitry Andric #include <__algorithm/unwrap_range.h> 17fe6060f1SDimitry Andric #include <__config> 1881ad6265SDimitry Andric #include <__iterator/iterator_traits.h> 19972a253aSDimitry Andric #include <__iterator/reverse_iterator.h> 20fe6060f1SDimitry Andric #include <__memory/addressof.h> 2181ad6265SDimitry Andric #include <__memory/allocator_traits.h> 22fe6060f1SDimitry Andric #include <__memory/construct_at.h> 23972a253aSDimitry Andric #include <__memory/pointer_traits.h> 240eae32dcSDimitry Andric #include <__memory/voidify.h> 25bdd1243dSDimitry Andric #include <__type_traits/extent.h> 26bdd1243dSDimitry Andric #include <__type_traits/is_array.h> 27972a253aSDimitry Andric #include <__type_traits/is_constant_evaluated.h> 28*0fca6ea1SDimitry Andric #include <__type_traits/is_trivially_assignable.h> 29*0fca6ea1SDimitry Andric #include <__type_traits/is_trivially_constructible.h> 30*0fca6ea1SDimitry Andric #include <__type_traits/is_trivially_relocatable.h> 31bdd1243dSDimitry Andric #include <__type_traits/is_unbounded_array.h> 32bdd1243dSDimitry Andric #include <__type_traits/negation.h> 33bdd1243dSDimitry Andric #include <__type_traits/remove_const.h> 34bdd1243dSDimitry Andric #include <__type_traits/remove_extent.h> 35bdd1243dSDimitry Andric #include <__utility/exception_guard.h> 3681ad6265SDimitry Andric #include <__utility/move.h> 3781ad6265SDimitry Andric #include <__utility/pair.h> 38bdd1243dSDimitry Andric #include <new> 39fe6060f1SDimitry Andric 40fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 41fe6060f1SDimitry Andric # pragma GCC system_header 42fe6060f1SDimitry Andric #endif 43fe6060f1SDimitry Andric 44b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS 45b3edf446SDimitry Andric #include <__undef_macros> 46b3edf446SDimitry Andric 47fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 48fe6060f1SDimitry Andric 495f757f3fSDimitry Andric struct __always_false { 505f757f3fSDimitry Andric template <class... _Args> 515f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator()(_Args&&...) const _NOEXCEPT { 525f757f3fSDimitry Andric return false; 53fe6060f1SDimitry Andric } 5404eeddc0SDimitry Andric }; 5504eeddc0SDimitry Andric 5604eeddc0SDimitry Andric // uninitialized_copy 5704eeddc0SDimitry Andric 585f757f3fSDimitry Andric template <class _ValueType, class _InputIterator, class _Sentinel1, class _ForwardIterator, class _EndPredicate> 595f757f3fSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_copy( 605f757f3fSDimitry Andric _InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _EndPredicate __stop_copying) { 6104eeddc0SDimitry Andric _ForwardIterator __idx = __ofirst; 6206c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 6304eeddc0SDimitry Andric try { 6404eeddc0SDimitry Andric #endif 655f757f3fSDimitry Andric for (; __ifirst != __ilast && !__stop_copying(__idx); ++__ifirst, (void)++__idx) 665f757f3fSDimitry Andric ::new (std::__voidify(*__idx)) _ValueType(*__ifirst); 6706c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 6804eeddc0SDimitry Andric } catch (...) { 695f757f3fSDimitry Andric std::__destroy(__ofirst, __idx); 70fe6060f1SDimitry Andric throw; 71fe6060f1SDimitry Andric } 72fe6060f1SDimitry Andric #endif 7304eeddc0SDimitry Andric 745f757f3fSDimitry Andric return pair<_InputIterator, _ForwardIterator>(std::move(__ifirst), std::move(__idx)); 7504eeddc0SDimitry Andric } 7604eeddc0SDimitry Andric 7704eeddc0SDimitry Andric template <class _InputIterator, class _ForwardIterator> 78cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _ForwardIterator 79cb14a3feSDimitry Andric uninitialized_copy(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIterator __ofirst) { 8004eeddc0SDimitry Andric typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; 815f757f3fSDimitry Andric auto __result = std::__uninitialized_copy<_ValueType>( 825f757f3fSDimitry Andric std::move(__ifirst), std::move(__ilast), std::move(__ofirst), __always_false()); 835f757f3fSDimitry Andric return std::move(__result.second); 8404eeddc0SDimitry Andric } 8504eeddc0SDimitry Andric 8604eeddc0SDimitry Andric // uninitialized_copy_n 8704eeddc0SDimitry Andric 885f757f3fSDimitry Andric template <class _ValueType, class _InputIterator, class _Size, class _ForwardIterator, class _EndPredicate> 89cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> 90cb14a3feSDimitry Andric __uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _EndPredicate __stop_copying) { 9104eeddc0SDimitry Andric _ForwardIterator __idx = __ofirst; 9206c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 9304eeddc0SDimitry Andric try { 9404eeddc0SDimitry Andric #endif 955f757f3fSDimitry Andric for (; __n > 0 && !__stop_copying(__idx); ++__ifirst, (void)++__idx, (void)--__n) 965f757f3fSDimitry Andric ::new (std::__voidify(*__idx)) _ValueType(*__ifirst); 9706c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 9804eeddc0SDimitry Andric } catch (...) { 995f757f3fSDimitry Andric std::__destroy(__ofirst, __idx); 10004eeddc0SDimitry Andric throw; 10104eeddc0SDimitry Andric } 10204eeddc0SDimitry Andric #endif 10304eeddc0SDimitry Andric 1045f757f3fSDimitry Andric return pair<_InputIterator, _ForwardIterator>(std::move(__ifirst), std::move(__idx)); 105fe6060f1SDimitry Andric } 106fe6060f1SDimitry Andric 107fe6060f1SDimitry Andric template <class _InputIterator, class _Size, class _ForwardIterator> 108cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 109cb14a3feSDimitry Andric uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) { 11004eeddc0SDimitry Andric typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; 1115f757f3fSDimitry Andric auto __result = 1125f757f3fSDimitry Andric std::__uninitialized_copy_n<_ValueType>(std::move(__ifirst), __n, std::move(__ofirst), __always_false()); 1135f757f3fSDimitry Andric return std::move(__result.second); 114fe6060f1SDimitry Andric } 115fe6060f1SDimitry Andric 1160eae32dcSDimitry Andric // uninitialized_fill 1170eae32dcSDimitry Andric 1180eae32dcSDimitry Andric template <class _ValueType, class _ForwardIterator, class _Sentinel, class _Tp> 119cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 120cb14a3feSDimitry Andric __uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) { 1210eae32dcSDimitry Andric _ForwardIterator __idx = __first; 12206c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 123cb14a3feSDimitry Andric try { 124fe6060f1SDimitry Andric #endif 1250eae32dcSDimitry Andric for (; __idx != __last; ++__idx) 1265f757f3fSDimitry Andric ::new (std::__voidify(*__idx)) _ValueType(__x); 12706c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 128cb14a3feSDimitry Andric } catch (...) { 1295f757f3fSDimitry Andric std::__destroy(__first, __idx); 130fe6060f1SDimitry Andric throw; 131fe6060f1SDimitry Andric } 132fe6060f1SDimitry Andric #endif 1330eae32dcSDimitry Andric 1340eae32dcSDimitry Andric return __idx; 1350eae32dcSDimitry Andric } 1360eae32dcSDimitry Andric 1370eae32dcSDimitry Andric template <class _ForwardIterator, class _Tp> 138cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void 139cb14a3feSDimitry Andric uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __x) { 1400eae32dcSDimitry Andric typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; 1415f757f3fSDimitry Andric (void)std::__uninitialized_fill<_ValueType>(__first, __last, __x); 1420eae32dcSDimitry Andric } 1430eae32dcSDimitry Andric 1440eae32dcSDimitry Andric // uninitialized_fill_n 1450eae32dcSDimitry Andric 1460eae32dcSDimitry Andric template <class _ValueType, class _ForwardIterator, class _Size, class _Tp> 147cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 148cb14a3feSDimitry Andric __uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) { 1490eae32dcSDimitry Andric _ForwardIterator __idx = __first; 15006c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 151cb14a3feSDimitry Andric try { 1520eae32dcSDimitry Andric #endif 1530eae32dcSDimitry Andric for (; __n > 0; ++__idx, (void)--__n) 1545f757f3fSDimitry Andric ::new (std::__voidify(*__idx)) _ValueType(__x); 15506c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 156cb14a3feSDimitry Andric } catch (...) { 1575f757f3fSDimitry Andric std::__destroy(__first, __idx); 1580eae32dcSDimitry Andric throw; 1590eae32dcSDimitry Andric } 1600eae32dcSDimitry Andric #endif 1610eae32dcSDimitry Andric 1620eae32dcSDimitry Andric return __idx; 163fe6060f1SDimitry Andric } 164fe6060f1SDimitry Andric 165fe6060f1SDimitry Andric template <class _ForwardIterator, class _Size, class _Tp> 166cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 167cb14a3feSDimitry Andric uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) { 1680eae32dcSDimitry Andric typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; 1695f757f3fSDimitry Andric return std::__uninitialized_fill_n<_ValueType>(__first, __n, __x); 170fe6060f1SDimitry Andric } 171fe6060f1SDimitry Andric 17206c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 173fe6060f1SDimitry Andric 1740eae32dcSDimitry Andric // uninitialized_default_construct 1750eae32dcSDimitry Andric 1760eae32dcSDimitry Andric template <class _ValueType, class _ForwardIterator, class _Sentinel> 177cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 178cb14a3feSDimitry Andric __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) { 1790eae32dcSDimitry Andric auto __idx = __first; 18006c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 1810eae32dcSDimitry Andric try { 1820eae32dcSDimitry Andric # endif 1830eae32dcSDimitry Andric for (; __idx != __last; ++__idx) 1845f757f3fSDimitry Andric ::new (std::__voidify(*__idx)) _ValueType; 18506c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 1860eae32dcSDimitry Andric } catch (...) { 1875f757f3fSDimitry Andric std::__destroy(__first, __idx); 1880eae32dcSDimitry Andric throw; 1890eae32dcSDimitry Andric } 1900eae32dcSDimitry Andric # endif 1910eae32dcSDimitry Andric 1920eae32dcSDimitry Andric return __idx; 1930eae32dcSDimitry Andric } 1940eae32dcSDimitry Andric 195fe6060f1SDimitry Andric template <class _ForwardIterator> 196cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) { 1970eae32dcSDimitry Andric using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 198cb14a3feSDimitry Andric (void)std::__uninitialized_default_construct<_ValueType>(std::move(__first), std::move(__last)); 199fe6060f1SDimitry Andric } 200fe6060f1SDimitry Andric 2010eae32dcSDimitry Andric // uninitialized_default_construct_n 2020eae32dcSDimitry Andric 2030eae32dcSDimitry Andric template <class _ValueType, class _ForwardIterator, class _Size> 204cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) { 205fe6060f1SDimitry Andric auto __idx = __first; 20606c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 207fe6060f1SDimitry Andric try { 208fe6060f1SDimitry Andric # endif 209349cc55cSDimitry Andric for (; __n > 0; ++__idx, (void)--__n) 2105f757f3fSDimitry Andric ::new (std::__voidify(*__idx)) _ValueType; 21106c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 212fe6060f1SDimitry Andric } catch (...) { 2135f757f3fSDimitry Andric std::__destroy(__first, __idx); 214fe6060f1SDimitry Andric throw; 215fe6060f1SDimitry Andric } 216fe6060f1SDimitry Andric # endif 2170eae32dcSDimitry Andric 2180eae32dcSDimitry Andric return __idx; 219fe6060f1SDimitry Andric } 220fe6060f1SDimitry Andric 2210eae32dcSDimitry Andric template <class _ForwardIterator, class _Size> 222cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) { 2230eae32dcSDimitry Andric using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 2245f757f3fSDimitry Andric return std::__uninitialized_default_construct_n<_ValueType>(std::move(__first), __n); 2250eae32dcSDimitry Andric } 2260eae32dcSDimitry Andric 2270eae32dcSDimitry Andric // uninitialized_value_construct 2280eae32dcSDimitry Andric 2290eae32dcSDimitry Andric template <class _ValueType, class _ForwardIterator, class _Sentinel> 230cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 231cb14a3feSDimitry Andric __uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) { 2320eae32dcSDimitry Andric auto __idx = __first; 23306c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 2340eae32dcSDimitry Andric try { 2350eae32dcSDimitry Andric # endif 2360eae32dcSDimitry Andric for (; __idx != __last; ++__idx) 2375f757f3fSDimitry Andric ::new (std::__voidify(*__idx)) _ValueType(); 23806c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 2390eae32dcSDimitry Andric } catch (...) { 2405f757f3fSDimitry Andric std::__destroy(__first, __idx); 2410eae32dcSDimitry Andric throw; 2420eae32dcSDimitry Andric } 2430eae32dcSDimitry Andric # endif 2440eae32dcSDimitry Andric 2450eae32dcSDimitry Andric return __idx; 2460eae32dcSDimitry Andric } 247fe6060f1SDimitry Andric 248fe6060f1SDimitry Andric template <class _ForwardIterator> 249cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) { 2500eae32dcSDimitry Andric using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 251cb14a3feSDimitry Andric (void)std::__uninitialized_value_construct<_ValueType>(std::move(__first), std::move(__last)); 252fe6060f1SDimitry Andric } 253fe6060f1SDimitry Andric 2540eae32dcSDimitry Andric // uninitialized_value_construct_n 2550eae32dcSDimitry Andric 2560eae32dcSDimitry Andric template <class _ValueType, class _ForwardIterator, class _Size> 257cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { 258fe6060f1SDimitry Andric auto __idx = __first; 25906c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 260fe6060f1SDimitry Andric try { 261fe6060f1SDimitry Andric # endif 262349cc55cSDimitry Andric for (; __n > 0; ++__idx, (void)--__n) 2635f757f3fSDimitry Andric ::new (std::__voidify(*__idx)) _ValueType(); 26406c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 265fe6060f1SDimitry Andric } catch (...) { 2665f757f3fSDimitry Andric std::__destroy(__first, __idx); 267fe6060f1SDimitry Andric throw; 268fe6060f1SDimitry Andric } 269fe6060f1SDimitry Andric # endif 2700eae32dcSDimitry Andric 2710eae32dcSDimitry Andric return __idx; 272fe6060f1SDimitry Andric } 273fe6060f1SDimitry Andric 2740eae32dcSDimitry Andric template <class _ForwardIterator, class _Size> 275cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { 2760eae32dcSDimitry Andric using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 2775f757f3fSDimitry Andric return std::__uninitialized_value_construct_n<_ValueType>(std::move(__first), __n); 2780eae32dcSDimitry Andric } 279fe6060f1SDimitry Andric 28004eeddc0SDimitry Andric // uninitialized_move 28104eeddc0SDimitry Andric 2825f757f3fSDimitry Andric template <class _ValueType, 2835f757f3fSDimitry Andric class _InputIterator, 2845f757f3fSDimitry Andric class _Sentinel1, 2855f757f3fSDimitry Andric class _ForwardIterator, 2865f757f3fSDimitry Andric class _EndPredicate, 28704eeddc0SDimitry Andric class _IterMove> 2885f757f3fSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move( 2895f757f3fSDimitry Andric _InputIterator __ifirst, 2905f757f3fSDimitry Andric _Sentinel1 __ilast, 2915f757f3fSDimitry Andric _ForwardIterator __ofirst, 2925f757f3fSDimitry Andric _EndPredicate __stop_moving, 2935f757f3fSDimitry Andric _IterMove __iter_move) { 29404eeddc0SDimitry Andric auto __idx = __ofirst; 29506c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 296fe6060f1SDimitry Andric try { 297fe6060f1SDimitry Andric # endif 2985f757f3fSDimitry Andric for (; __ifirst != __ilast && !__stop_moving(__idx); ++__idx, (void)++__ifirst) { 2995f757f3fSDimitry Andric ::new (std::__voidify(*__idx)) _ValueType(__iter_move(__ifirst)); 30004eeddc0SDimitry Andric } 30106c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 302fe6060f1SDimitry Andric } catch (...) { 3035f757f3fSDimitry Andric std::__destroy(__ofirst, __idx); 304fe6060f1SDimitry Andric throw; 305fe6060f1SDimitry Andric } 306fe6060f1SDimitry Andric # endif 30704eeddc0SDimitry Andric 3085f757f3fSDimitry Andric return {std::move(__ifirst), std::move(__idx)}; 309fe6060f1SDimitry Andric } 310fe6060f1SDimitry Andric 31104eeddc0SDimitry Andric template <class _InputIterator, class _ForwardIterator> 312cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 313cb14a3feSDimitry Andric uninitialized_move(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIterator __ofirst) { 31404eeddc0SDimitry Andric using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 3155f757f3fSDimitry Andric auto __iter_move = [](auto&& __iter) -> decltype(auto) { return std::move(*__iter); }; 31604eeddc0SDimitry Andric 3175f757f3fSDimitry Andric auto __result = std::__uninitialized_move<_ValueType>( 3185f757f3fSDimitry Andric std::move(__ifirst), std::move(__ilast), std::move(__ofirst), __always_false(), __iter_move); 3195f757f3fSDimitry Andric return std::move(__result.second); 32004eeddc0SDimitry Andric } 32104eeddc0SDimitry Andric 32204eeddc0SDimitry Andric // uninitialized_move_n 32304eeddc0SDimitry Andric 3245f757f3fSDimitry Andric template <class _ValueType, 3255f757f3fSDimitry Andric class _InputIterator, 3265f757f3fSDimitry Andric class _Size, 3275f757f3fSDimitry Andric class _ForwardIterator, 3285f757f3fSDimitry Andric class _EndPredicate, 3295f757f3fSDimitry Andric class _IterMove> 3305f757f3fSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move_n( 3315f757f3fSDimitry Andric _InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _EndPredicate __stop_moving, _IterMove __iter_move) { 33204eeddc0SDimitry Andric auto __idx = __ofirst; 33306c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 334fe6060f1SDimitry Andric try { 335fe6060f1SDimitry Andric # endif 3365f757f3fSDimitry Andric for (; __n > 0 && !__stop_moving(__idx); ++__idx, (void)++__ifirst, --__n) 3375f757f3fSDimitry Andric ::new (std::__voidify(*__idx)) _ValueType(__iter_move(__ifirst)); 33806c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 339fe6060f1SDimitry Andric } catch (...) { 3405f757f3fSDimitry Andric std::__destroy(__ofirst, __idx); 341fe6060f1SDimitry Andric throw; 342fe6060f1SDimitry Andric } 343fe6060f1SDimitry Andric # endif 34404eeddc0SDimitry Andric 3455f757f3fSDimitry Andric return {std::move(__ifirst), std::move(__idx)}; 34604eeddc0SDimitry Andric } 34704eeddc0SDimitry Andric 34804eeddc0SDimitry Andric template <class _InputIterator, class _Size, class _ForwardIterator> 34904eeddc0SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> 35004eeddc0SDimitry Andric uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) { 35104eeddc0SDimitry Andric using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 3525f757f3fSDimitry Andric auto __iter_move = [](auto&& __iter) -> decltype(auto) { return std::move(*__iter); }; 35304eeddc0SDimitry Andric 3545f757f3fSDimitry Andric return std::__uninitialized_move_n<_ValueType>( 3555f757f3fSDimitry Andric std::move(__ifirst), __n, std::move(__ofirst), __always_false(), __iter_move); 356fe6060f1SDimitry Andric } 357fe6060f1SDimitry Andric 358972a253aSDimitry Andric // TODO: Rewrite this to iterate left to right and use reverse_iterators when calling 35981ad6265SDimitry Andric // Destroys every element in the range [first, last) FROM RIGHT TO LEFT using allocator 36081ad6265SDimitry Andric // destruction. If elements are themselves C-style arrays, they are recursively destroyed 36181ad6265SDimitry Andric // in the same manner. 36281ad6265SDimitry Andric // 36381ad6265SDimitry Andric // This function assumes that destructors do not throw, and that the allocator is bound to 36481ad6265SDimitry Andric // the correct type. 365cb14a3feSDimitry Andric template <class _Alloc, 366cb14a3feSDimitry Andric class _BidirIter, 367*0fca6ea1SDimitry Andric __enable_if_t<__has_bidirectional_iterator_category<_BidirIter>::value, int> = 0> 368cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void 369cb14a3feSDimitry Andric __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter __first, _BidirIter __last) noexcept { 37081ad6265SDimitry Andric using _ValueType = typename iterator_traits<_BidirIter>::value_type; 37181ad6265SDimitry Andric static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _ValueType>, 37281ad6265SDimitry Andric "The allocator should already be rebound to the correct type"); 37381ad6265SDimitry Andric 37481ad6265SDimitry Andric if (__first == __last) 37581ad6265SDimitry Andric return; 37681ad6265SDimitry Andric 37781ad6265SDimitry Andric if constexpr (is_array_v<_ValueType>) { 37881ad6265SDimitry Andric static_assert(!__libcpp_is_unbounded_array<_ValueType>::value, 37981ad6265SDimitry Andric "arrays of unbounded arrays don't exist, but if they did we would mess up here"); 38081ad6265SDimitry Andric 38181ad6265SDimitry Andric using _Element = remove_extent_t<_ValueType>; 38281ad6265SDimitry Andric __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc); 38381ad6265SDimitry Andric do { 38481ad6265SDimitry Andric --__last; 38581ad6265SDimitry Andric decltype(auto) __array = *__last; 38681ad6265SDimitry Andric std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + extent_v<_ValueType>); 38781ad6265SDimitry Andric } while (__last != __first); 38881ad6265SDimitry Andric } else { 38981ad6265SDimitry Andric do { 39081ad6265SDimitry Andric --__last; 39181ad6265SDimitry Andric allocator_traits<_Alloc>::destroy(__alloc, std::addressof(*__last)); 39281ad6265SDimitry Andric } while (__last != __first); 39381ad6265SDimitry Andric } 39481ad6265SDimitry Andric } 39581ad6265SDimitry Andric 39681ad6265SDimitry Andric // Constructs the object at the given location using the allocator's construct method. 39781ad6265SDimitry Andric // 39881ad6265SDimitry Andric // If the object being constructed is an array, each element of the array is allocator-constructed, 39981ad6265SDimitry Andric // recursively. If an exception is thrown during the construction of an array, the initialized 40081ad6265SDimitry Andric // elements are destroyed in reverse order of initialization using allocator destruction. 40181ad6265SDimitry Andric // 40281ad6265SDimitry Andric // This function assumes that the allocator is bound to the correct type. 40381ad6265SDimitry Andric template <class _Alloc, class _Tp> 404cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc) { 40581ad6265SDimitry Andric static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>, 40681ad6265SDimitry Andric "The allocator should already be rebound to the correct type"); 40781ad6265SDimitry Andric 40881ad6265SDimitry Andric if constexpr (is_array_v<_Tp>) { 40981ad6265SDimitry Andric using _Element = remove_extent_t<_Tp>; 41081ad6265SDimitry Andric __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc); 41181ad6265SDimitry Andric size_t __i = 0; 41281ad6265SDimitry Andric _Tp& __array = *__loc; 41381ad6265SDimitry Andric 41481ad6265SDimitry Andric // If an exception is thrown, destroy what we have constructed so far in reverse order. 4151ac55f4cSDimitry Andric auto __guard = std::__make_exception_guard([&]() { 416bdd1243dSDimitry Andric std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); 417bdd1243dSDimitry Andric }); 418bdd1243dSDimitry Andric 41981ad6265SDimitry Andric for (; __i != extent_v<_Tp>; ++__i) { 4201ac55f4cSDimitry Andric std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i])); 42181ad6265SDimitry Andric } 42281ad6265SDimitry Andric __guard.__complete(); 42381ad6265SDimitry Andric } else { 42481ad6265SDimitry Andric allocator_traits<_Alloc>::construct(__alloc, __loc); 42581ad6265SDimitry Andric } 42681ad6265SDimitry Andric } 42781ad6265SDimitry Andric 42881ad6265SDimitry Andric // Constructs the object at the given location using the allocator's construct method, passing along 42981ad6265SDimitry Andric // the provided argument. 43081ad6265SDimitry Andric // 43181ad6265SDimitry Andric // If the object being constructed is an array, the argument is also assumed to be an array. Each 43281ad6265SDimitry Andric // each element of the array being constructed is allocator-constructed from the corresponding 43381ad6265SDimitry Andric // element of the argument array. If an exception is thrown during the construction of an array, 43481ad6265SDimitry Andric // the initialized elements are destroyed in reverse order of initialization using allocator 43581ad6265SDimitry Andric // destruction. 43681ad6265SDimitry Andric // 43781ad6265SDimitry Andric // This function assumes that the allocator is bound to the correct type. 43881ad6265SDimitry Andric template <class _Alloc, class _Tp, class _Arg> 439cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void 440cb14a3feSDimitry Andric __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) { 44181ad6265SDimitry Andric static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>, 44281ad6265SDimitry Andric "The allocator should already be rebound to the correct type"); 44381ad6265SDimitry Andric 44481ad6265SDimitry Andric if constexpr (is_array_v<_Tp>) { 44581ad6265SDimitry Andric static_assert(is_array_v<_Arg>, 4461ac55f4cSDimitry Andric "Provided non-array initialization argument to __allocator_construct_at_multidimensional when " 44781ad6265SDimitry Andric "trying to construct an array."); 44881ad6265SDimitry Andric 44981ad6265SDimitry Andric using _Element = remove_extent_t<_Tp>; 45081ad6265SDimitry Andric __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc); 45181ad6265SDimitry Andric size_t __i = 0; 45281ad6265SDimitry Andric _Tp& __array = *__loc; 45381ad6265SDimitry Andric 45481ad6265SDimitry Andric // If an exception is thrown, destroy what we have constructed so far in reverse order. 4551ac55f4cSDimitry Andric auto __guard = std::__make_exception_guard([&]() { 456bdd1243dSDimitry Andric std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); 457bdd1243dSDimitry Andric }); 45881ad6265SDimitry Andric for (; __i != extent_v<_Tp>; ++__i) { 4591ac55f4cSDimitry Andric std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]), __arg[__i]); 46081ad6265SDimitry Andric } 46181ad6265SDimitry Andric __guard.__complete(); 46281ad6265SDimitry Andric } else { 46381ad6265SDimitry Andric allocator_traits<_Alloc>::construct(__alloc, __loc, __arg); 46481ad6265SDimitry Andric } 46581ad6265SDimitry Andric } 46681ad6265SDimitry Andric 46781ad6265SDimitry Andric // Given a range starting at it and containing n elements, initializes each element in the 46881ad6265SDimitry Andric // range from left to right using the construct method of the allocator (rebound to the 46981ad6265SDimitry Andric // correct type). 47081ad6265SDimitry Andric // 47181ad6265SDimitry Andric // If an exception is thrown, the initialized elements are destroyed in reverse order of 47281ad6265SDimitry Andric // initialization using allocator_traits destruction. If the elements in the range are C-style 47381ad6265SDimitry Andric // arrays, they are initialized element-wise using allocator construction, and recursively so. 474cb14a3feSDimitry Andric template <class _Alloc, 475cb14a3feSDimitry Andric class _BidirIter, 476cb14a3feSDimitry Andric class _Tp, 477cb14a3feSDimitry Andric class _Size = typename iterator_traits<_BidirIter>::difference_type> 4781ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void 4791ac55f4cSDimitry Andric __uninitialized_allocator_fill_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) { 48081ad6265SDimitry Andric using _ValueType = typename iterator_traits<_BidirIter>::value_type; 48181ad6265SDimitry Andric __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc); 48281ad6265SDimitry Andric _BidirIter __begin = __it; 48381ad6265SDimitry Andric 48481ad6265SDimitry Andric // If an exception is thrown, destroy what we have constructed so far in reverse order. 485cb14a3feSDimitry Andric auto __guard = 486cb14a3feSDimitry Andric std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); 48781ad6265SDimitry Andric for (; __n != 0; --__n, ++__it) { 4881ac55f4cSDimitry Andric std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it), __value); 48981ad6265SDimitry Andric } 49081ad6265SDimitry Andric __guard.__complete(); 49181ad6265SDimitry Andric } 49281ad6265SDimitry Andric 4931ac55f4cSDimitry Andric // Same as __uninitialized_allocator_fill_n_multidimensional, but doesn't pass any initialization argument 49481ad6265SDimitry Andric // to the allocator's construct method, which results in value initialization. 49581ad6265SDimitry Andric template <class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type> 4961ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void 4971ac55f4cSDimitry Andric __uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n) { 49881ad6265SDimitry Andric using _ValueType = typename iterator_traits<_BidirIter>::value_type; 49981ad6265SDimitry Andric __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc); 50081ad6265SDimitry Andric _BidirIter __begin = __it; 50181ad6265SDimitry Andric 50281ad6265SDimitry Andric // If an exception is thrown, destroy what we have constructed so far in reverse order. 503cb14a3feSDimitry Andric auto __guard = 504cb14a3feSDimitry Andric std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); 50581ad6265SDimitry Andric for (; __n != 0; --__n, ++__it) { 5061ac55f4cSDimitry Andric std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it)); 50781ad6265SDimitry Andric } 50881ad6265SDimitry Andric __guard.__complete(); 50981ad6265SDimitry Andric } 51081ad6265SDimitry Andric 51106c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 17 512fe6060f1SDimitry Andric 513972a253aSDimitry Andric // Destroy all elements in [__first, __last) from left to right using allocator destruction. 514972a253aSDimitry Andric template <class _Alloc, class _Iter, class _Sent> 515bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 516972a253aSDimitry Andric __allocator_destroy(_Alloc& __alloc, _Iter __first, _Sent __last) { 517972a253aSDimitry Andric for (; __first != __last; ++__first) 518972a253aSDimitry Andric allocator_traits<_Alloc>::destroy(__alloc, std::__to_address(__first)); 519972a253aSDimitry Andric } 520972a253aSDimitry Andric 521972a253aSDimitry Andric template <class _Alloc, class _Iter> 522972a253aSDimitry Andric class _AllocatorDestroyRangeReverse { 523972a253aSDimitry Andric public: 524bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 52561cfbce3SDimitry Andric _AllocatorDestroyRangeReverse(_Alloc& __alloc, _Iter& __first, _Iter& __last) 526972a253aSDimitry Andric : __alloc_(__alloc), __first_(__first), __last_(__last) {} 527972a253aSDimitry Andric 528bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void operator()() const { 529972a253aSDimitry Andric std::__allocator_destroy(__alloc_, std::reverse_iterator<_Iter>(__last_), std::reverse_iterator<_Iter>(__first_)); 530972a253aSDimitry Andric } 531972a253aSDimitry Andric 532972a253aSDimitry Andric private: 533972a253aSDimitry Andric _Alloc& __alloc_; 534972a253aSDimitry Andric _Iter& __first_; 535972a253aSDimitry Andric _Iter& __last_; 536972a253aSDimitry Andric }; 537972a253aSDimitry Andric 538972a253aSDimitry Andric // Copy-construct [__first1, __last1) in [__first2, __first2 + N), where N is distance(__first1, __last1). 539972a253aSDimitry Andric // 540972a253aSDimitry Andric // The caller has to ensure that __first2 can hold at least N uninitialized elements. If an exception is thrown the 541972a253aSDimitry Andric // already copied elements are destroyed in reverse order of their construction. 542972a253aSDimitry Andric template <class _Alloc, class _Iter1, class _Sent1, class _Iter2> 543bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 54406c3fb27SDimitry Andric __uninitialized_allocator_copy_impl(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { 545972a253aSDimitry Andric auto __destruct_first = __first2; 546bdd1243dSDimitry Andric auto __guard = 547bdd1243dSDimitry Andric std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); 548972a253aSDimitry Andric while (__first1 != __last1) { 549972a253aSDimitry Andric allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), *__first1); 550972a253aSDimitry Andric ++__first1; 551972a253aSDimitry Andric ++__first2; 552972a253aSDimitry Andric } 553bdd1243dSDimitry Andric __guard.__complete(); 554972a253aSDimitry Andric return __first2; 555972a253aSDimitry Andric } 556972a253aSDimitry Andric 557972a253aSDimitry Andric template <class _Alloc, class _Type> 558972a253aSDimitry Andric struct __allocator_has_trivial_copy_construct : _Not<__has_construct<_Alloc, _Type*, const _Type&> > {}; 559972a253aSDimitry Andric 560972a253aSDimitry Andric template <class _Type> 561972a253aSDimitry Andric struct __allocator_has_trivial_copy_construct<allocator<_Type>, _Type> : true_type {}; 562972a253aSDimitry Andric 563972a253aSDimitry Andric template <class _Alloc, 56406c3fb27SDimitry Andric class _In, 56506c3fb27SDimitry Andric class _RawTypeIn = __remove_const_t<_In>, 56606c3fb27SDimitry Andric class _Out, 567972a253aSDimitry Andric __enable_if_t< 56806c3fb27SDimitry Andric // using _RawTypeIn because of the allocator<T const> extension 56906c3fb27SDimitry Andric is_trivially_copy_constructible<_RawTypeIn>::value && is_trivially_copy_assignable<_RawTypeIn>::value && 57006c3fb27SDimitry Andric is_same<__remove_const_t<_In>, __remove_const_t<_Out> >::value && 571*0fca6ea1SDimitry Andric __allocator_has_trivial_copy_construct<_Alloc, _RawTypeIn>::value, 572*0fca6ea1SDimitry Andric int> = 0> 57306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Out* 57406c3fb27SDimitry Andric __uninitialized_allocator_copy_impl(_Alloc&, _In* __first1, _In* __last1, _Out* __first2) { 575972a253aSDimitry Andric // TODO: Remove the const_cast once we drop support for std::allocator<T const> 576972a253aSDimitry Andric if (__libcpp_is_constant_evaluated()) { 577972a253aSDimitry Andric while (__first1 != __last1) { 578972a253aSDimitry Andric std::__construct_at(std::__to_address(__first2), *__first1); 579972a253aSDimitry Andric ++__first1; 580972a253aSDimitry Andric ++__first2; 581972a253aSDimitry Andric } 582972a253aSDimitry Andric return __first2; 583972a253aSDimitry Andric } else { 58406c3fb27SDimitry Andric return std::copy(__first1, __last1, const_cast<_RawTypeIn*>(__first2)); 585972a253aSDimitry Andric } 586972a253aSDimitry Andric } 587972a253aSDimitry Andric 58806c3fb27SDimitry Andric template <class _Alloc, class _Iter1, class _Sent1, class _Iter2> 589cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 590cb14a3feSDimitry Andric __uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { 59106c3fb27SDimitry Andric auto __unwrapped_range = std::__unwrap_range(__first1, __last1); 592cb14a3feSDimitry Andric auto __result = std::__uninitialized_allocator_copy_impl( 593cb14a3feSDimitry Andric __alloc, __unwrapped_range.first, __unwrapped_range.second, std::__unwrap_iter(__first2)); 59406c3fb27SDimitry Andric return std::__rewrap_iter(__first2, __result); 59506c3fb27SDimitry Andric } 59606c3fb27SDimitry Andric 597972a253aSDimitry Andric template <class _Alloc, class _Type> 598972a253aSDimitry Andric struct __allocator_has_trivial_move_construct : _Not<__has_construct<_Alloc, _Type*, _Type&&> > {}; 599972a253aSDimitry Andric 600972a253aSDimitry Andric template <class _Type> 601972a253aSDimitry Andric struct __allocator_has_trivial_move_construct<allocator<_Type>, _Type> : true_type {}; 602972a253aSDimitry Andric 603*0fca6ea1SDimitry Andric template <class _Alloc, class _Tp> 604*0fca6ea1SDimitry Andric struct __allocator_has_trivial_destroy : _Not<__has_destroy<_Alloc, _Tp*> > {}; 605*0fca6ea1SDimitry Andric 606*0fca6ea1SDimitry Andric template <class _Tp, class _Up> 607*0fca6ea1SDimitry Andric struct __allocator_has_trivial_destroy<allocator<_Tp>, _Up> : true_type {}; 608*0fca6ea1SDimitry Andric 609*0fca6ea1SDimitry Andric // __uninitialized_allocator_relocate relocates the objects in [__first, __last) into __result. 610*0fca6ea1SDimitry Andric // Relocation means that the objects in [__first, __last) are placed into __result as-if by move-construct and destroy, 611*0fca6ea1SDimitry Andric // except that the move constructor and destructor may never be called if they are known to be equivalent to a memcpy. 612*0fca6ea1SDimitry Andric // 613*0fca6ea1SDimitry Andric // Preconditions: __result doesn't contain any objects and [__first, __last) contains objects 614*0fca6ea1SDimitry Andric // Postconditions: __result contains the objects from [__first, __last) and 615*0fca6ea1SDimitry Andric // [__first, __last) doesn't contain any objects 616*0fca6ea1SDimitry Andric // 617*0fca6ea1SDimitry Andric // The strong exception guarantee is provided if any of the following are true: 618*0fca6ea1SDimitry Andric // - is_nothrow_move_constructible<_Tp> 619*0fca6ea1SDimitry Andric // - is_copy_constructible<_Tp> 620*0fca6ea1SDimitry Andric // - __libcpp_is_trivially_relocatable<_Tp> 621*0fca6ea1SDimitry Andric template <class _Alloc, class _Tp> 622*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void 623*0fca6ea1SDimitry Andric __uninitialized_allocator_relocate(_Alloc& __alloc, _Tp* __first, _Tp* __last, _Tp* __result) { 624*0fca6ea1SDimitry Andric static_assert(__is_cpp17_move_insertable<_Alloc>::value, 625*0fca6ea1SDimitry Andric "The specified type does not meet the requirements of Cpp17MoveInsertable"); 626*0fca6ea1SDimitry Andric if (__libcpp_is_constant_evaluated() || !__libcpp_is_trivially_relocatable<_Tp>::value || 627*0fca6ea1SDimitry Andric !__allocator_has_trivial_move_construct<_Alloc, _Tp>::value || 628*0fca6ea1SDimitry Andric !__allocator_has_trivial_destroy<_Alloc, _Tp>::value) { 629*0fca6ea1SDimitry Andric auto __destruct_first = __result; 630*0fca6ea1SDimitry Andric auto __guard = 631*0fca6ea1SDimitry Andric std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Tp*>(__alloc, __destruct_first, __result)); 632*0fca6ea1SDimitry Andric auto __iter = __first; 633*0fca6ea1SDimitry Andric while (__iter != __last) { 634*0fca6ea1SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 635*0fca6ea1SDimitry Andric allocator_traits<_Alloc>::construct(__alloc, __result, std::move_if_noexcept(*__iter)); 636*0fca6ea1SDimitry Andric #else 637*0fca6ea1SDimitry Andric allocator_traits<_Alloc>::construct(__alloc, __result, std::move(*__iter)); 638*0fca6ea1SDimitry Andric #endif 639*0fca6ea1SDimitry Andric ++__iter; 640*0fca6ea1SDimitry Andric ++__result; 641972a253aSDimitry Andric } 642*0fca6ea1SDimitry Andric __guard.__complete(); 643*0fca6ea1SDimitry Andric std::__allocator_destroy(__alloc, __first, __last); 644972a253aSDimitry Andric } else { 645*0fca6ea1SDimitry Andric __builtin_memcpy(const_cast<__remove_const_t<_Tp>*>(__result), __first, sizeof(_Tp) * (__last - __first)); 646972a253aSDimitry Andric } 647972a253aSDimitry Andric } 648972a253aSDimitry Andric 649fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 650fe6060f1SDimitry Andric 651b3edf446SDimitry Andric _LIBCPP_POP_MACROS 652b3edf446SDimitry Andric 653fe6060f1SDimitry Andric #endif // _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H 654