14f9b2469SLouis Dionne // -*- C++ -*- 24f9b2469SLouis Dionne //===----------------------------------------------------------------------===// 34f9b2469SLouis Dionne // 44f9b2469SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 54f9b2469SLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 64f9b2469SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 74f9b2469SLouis Dionne // 84f9b2469SLouis Dionne //===----------------------------------------------------------------------===// 94f9b2469SLouis Dionne 104f9b2469SLouis Dionne #ifndef _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H 114f9b2469SLouis Dionne #define _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H 124f9b2469SLouis Dionne 13f4fb72e6SNikolas Klauser #include <__algorithm/copy.h> 14f4fb72e6SNikolas Klauser #include <__algorithm/move.h> 1563a2b206SAdityaK #include <__algorithm/unwrap_iter.h> 1663a2b206SAdityaK #include <__algorithm/unwrap_range.h> 174f9b2469SLouis Dionne #include <__config> 189474e094SLouis Dionne #include <__cstddef/size_t.h> 19ea2206d7SArthur O'Dwyer #include <__iterator/iterator_traits.h> 20f4fb72e6SNikolas Klauser #include <__iterator/reverse_iterator.h> 21f992cfbaSLouis Dionne #include <__memory/addressof.h> 22e27a122bSLouis Dionne #include <__memory/allocator_traits.h> 23f992cfbaSLouis Dionne #include <__memory/construct_at.h> 24f4fb72e6SNikolas Klauser #include <__memory/pointer_traits.h> 25e4fdbcc2SLouis Dionne #include <__type_traits/enable_if.h> 26e0a66116SNikolas Klauser #include <__type_traits/extent.h> 27e0a66116SNikolas Klauser #include <__type_traits/is_array.h> 28f4fb72e6SNikolas Klauser #include <__type_traits/is_constant_evaluated.h> 29de87dda2SNikolas Klauser #include <__type_traits/is_same.h> 30580f6048SNikolas Klauser #include <__type_traits/is_trivially_assignable.h> 31580f6048SNikolas Klauser #include <__type_traits/is_trivially_constructible.h> 324e112e5cSNikolas Klauser #include <__type_traits/is_trivially_relocatable.h> 33e0a66116SNikolas Klauser #include <__type_traits/is_unbounded_array.h> 34e0a66116SNikolas Klauser #include <__type_traits/negation.h> 35e0a66116SNikolas Klauser #include <__type_traits/remove_const.h> 36e0a66116SNikolas Klauser #include <__type_traits/remove_extent.h> 377458908fSNikolas Klauser #include <__utility/exception_guard.h> 38ea2206d7SArthur O'Dwyer #include <__utility/move.h> 39ea2206d7SArthur O'Dwyer #include <__utility/pair.h> 404f9b2469SLouis Dionne 414f9b2469SLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 424f9b2469SLouis Dionne # pragma GCC system_header 434f9b2469SLouis Dionne #endif 444f9b2469SLouis Dionne 457b462251SLouis Dionne _LIBCPP_PUSH_MACROS 467b462251SLouis Dionne #include <__undef_macros> 477b462251SLouis Dionne 484f9b2469SLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD 494f9b2469SLouis Dionne 507961fa36SLouis Dionne struct __always_false { 517961fa36SLouis Dionne template <class... _Args> 527961fa36SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator()(_Args&&...) const _NOEXCEPT { 537961fa36SLouis Dionne return false; 544f9b2469SLouis Dionne } 558d23b742SKonstantin Varlamov }; 568d23b742SKonstantin Varlamov 578d23b742SKonstantin Varlamov // uninitialized_copy 588d23b742SKonstantin Varlamov 597961fa36SLouis Dionne template <class _ValueType, class _InputIterator, class _Sentinel1, class _ForwardIterator, class _EndPredicate> 607961fa36SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_copy( 617961fa36SLouis Dionne _InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _EndPredicate __stop_copying) { 628d23b742SKonstantin Varlamov _ForwardIterator __idx = __ofirst; 63ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 648d23b742SKonstantin Varlamov try { 658d23b742SKonstantin Varlamov #endif 667961fa36SLouis Dionne for (; __ifirst != __ilast && !__stop_copying(__idx); ++__ifirst, (void)++__idx) 6719c6958dSA. Jiang ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(*__ifirst); 68ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 698d23b742SKonstantin Varlamov } catch (...) { 7077a00c0dSLouis Dionne std::__destroy(__ofirst, __idx); 714f9b2469SLouis Dionne throw; 724f9b2469SLouis Dionne } 734f9b2469SLouis Dionne #endif 748d23b742SKonstantin Varlamov 7577a00c0dSLouis Dionne return pair<_InputIterator, _ForwardIterator>(std::move(__ifirst), std::move(__idx)); 768d23b742SKonstantin Varlamov } 778d23b742SKonstantin Varlamov 788d23b742SKonstantin Varlamov template <class _InputIterator, class _ForwardIterator> 799783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _ForwardIterator 809783f28cSLouis Dionne uninitialized_copy(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIterator __ofirst) { 818d23b742SKonstantin Varlamov typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; 827961fa36SLouis Dionne auto __result = std::__uninitialized_copy<_ValueType>( 837961fa36SLouis Dionne std::move(__ifirst), std::move(__ilast), std::move(__ofirst), __always_false()); 8477a00c0dSLouis Dionne return std::move(__result.second); 858d23b742SKonstantin Varlamov } 868d23b742SKonstantin Varlamov 878d23b742SKonstantin Varlamov // uninitialized_copy_n 888d23b742SKonstantin Varlamov 897961fa36SLouis Dionne template <class _ValueType, class _InputIterator, class _Size, class _ForwardIterator, class _EndPredicate> 909783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> 919783f28cSLouis Dionne __uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _EndPredicate __stop_copying) { 928d23b742SKonstantin Varlamov _ForwardIterator __idx = __ofirst; 93ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 948d23b742SKonstantin Varlamov try { 958d23b742SKonstantin Varlamov #endif 967961fa36SLouis Dionne for (; __n > 0 && !__stop_copying(__idx); ++__ifirst, (void)++__idx, (void)--__n) 9719c6958dSA. Jiang ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(*__ifirst); 98ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 998d23b742SKonstantin Varlamov } catch (...) { 10077a00c0dSLouis Dionne std::__destroy(__ofirst, __idx); 1018d23b742SKonstantin Varlamov throw; 1028d23b742SKonstantin Varlamov } 1038d23b742SKonstantin Varlamov #endif 1048d23b742SKonstantin Varlamov 10577a00c0dSLouis Dionne return pair<_InputIterator, _ForwardIterator>(std::move(__ifirst), std::move(__idx)); 1064f9b2469SLouis Dionne } 1074f9b2469SLouis Dionne 1084f9b2469SLouis Dionne template <class _InputIterator, class _Size, class _ForwardIterator> 1099783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 1109783f28cSLouis Dionne uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) { 1118d23b742SKonstantin Varlamov typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; 1127961fa36SLouis Dionne auto __result = 1137961fa36SLouis Dionne std::__uninitialized_copy_n<_ValueType>(std::move(__ifirst), __n, std::move(__ofirst), __always_false()); 11477a00c0dSLouis Dionne return std::move(__result.second); 1154f9b2469SLouis Dionne } 1164f9b2469SLouis Dionne 117754ea6fdSKonstantin Varlamov // uninitialized_fill 118754ea6fdSKonstantin Varlamov 119754ea6fdSKonstantin Varlamov template <class _ValueType, class _ForwardIterator, class _Sentinel, class _Tp> 1209783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 1219783f28cSLouis Dionne __uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) { 122754ea6fdSKonstantin Varlamov _ForwardIterator __idx = __first; 123ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 1249783f28cSLouis Dionne try { 1254f9b2469SLouis Dionne #endif 126754ea6fdSKonstantin Varlamov for (; __idx != __last; ++__idx) 12719c6958dSA. Jiang ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__x); 128ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 1299783f28cSLouis Dionne } catch (...) { 13077a00c0dSLouis Dionne std::__destroy(__first, __idx); 1314f9b2469SLouis Dionne throw; 1324f9b2469SLouis Dionne } 1334f9b2469SLouis Dionne #endif 134754ea6fdSKonstantin Varlamov 135754ea6fdSKonstantin Varlamov return __idx; 136754ea6fdSKonstantin Varlamov } 137754ea6fdSKonstantin Varlamov 138754ea6fdSKonstantin Varlamov template <class _ForwardIterator, class _Tp> 1399783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI void 1409783f28cSLouis Dionne uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __x) { 141754ea6fdSKonstantin Varlamov typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; 14277a00c0dSLouis Dionne (void)std::__uninitialized_fill<_ValueType>(__first, __last, __x); 143754ea6fdSKonstantin Varlamov } 144754ea6fdSKonstantin Varlamov 145754ea6fdSKonstantin Varlamov // uninitialized_fill_n 146754ea6fdSKonstantin Varlamov 147754ea6fdSKonstantin Varlamov template <class _ValueType, class _ForwardIterator, class _Size, class _Tp> 1489783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 1499783f28cSLouis Dionne __uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) { 150754ea6fdSKonstantin Varlamov _ForwardIterator __idx = __first; 151ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 1529783f28cSLouis Dionne try { 153754ea6fdSKonstantin Varlamov #endif 154754ea6fdSKonstantin Varlamov for (; __n > 0; ++__idx, (void)--__n) 15519c6958dSA. Jiang ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__x); 156ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 1579783f28cSLouis Dionne } catch (...) { 15877a00c0dSLouis Dionne std::__destroy(__first, __idx); 159754ea6fdSKonstantin Varlamov throw; 160754ea6fdSKonstantin Varlamov } 161754ea6fdSKonstantin Varlamov #endif 162754ea6fdSKonstantin Varlamov 163754ea6fdSKonstantin Varlamov return __idx; 1644f9b2469SLouis Dionne } 1654f9b2469SLouis Dionne 1664f9b2469SLouis Dionne template <class _ForwardIterator, class _Size, class _Tp> 1679783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 1689783f28cSLouis Dionne uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) { 169754ea6fdSKonstantin Varlamov typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; 17077a00c0dSLouis Dionne return std::__uninitialized_fill_n<_ValueType>(__first, __n, __x); 1714f9b2469SLouis Dionne } 1724f9b2469SLouis Dionne 1734f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 17 1744f9b2469SLouis Dionne 1753f630cffSKonstantin Varlamov // uninitialized_default_construct 1763f630cffSKonstantin Varlamov 1773f630cffSKonstantin Varlamov template <class _ValueType, class _ForwardIterator, class _Sentinel> 1789783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 1799783f28cSLouis Dionne __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) { 1804f9b2469SLouis Dionne auto __idx = __first; 181ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 1824f9b2469SLouis Dionne try { 1834f9b2469SLouis Dionne # endif 1844f9b2469SLouis Dionne for (; __idx != __last; ++__idx) 18519c6958dSA. Jiang ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType; 186ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 1874f9b2469SLouis Dionne } catch (...) { 18877a00c0dSLouis Dionne std::__destroy(__first, __idx); 1894f9b2469SLouis Dionne throw; 1904f9b2469SLouis Dionne } 1914f9b2469SLouis Dionne # endif 1923f630cffSKonstantin Varlamov 1933f630cffSKonstantin Varlamov return __idx; 1944f9b2469SLouis Dionne } 1954f9b2469SLouis Dionne 1963f630cffSKonstantin Varlamov template <class _ForwardIterator> 1979783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) { 1983f630cffSKonstantin Varlamov using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 1999783f28cSLouis Dionne (void)std::__uninitialized_default_construct<_ValueType>(std::move(__first), std::move(__last)); 2003f630cffSKonstantin Varlamov } 2013f630cffSKonstantin Varlamov 2023f630cffSKonstantin Varlamov // uninitialized_default_construct_n 2033f630cffSKonstantin Varlamov 2043f630cffSKonstantin Varlamov template <class _ValueType, class _ForwardIterator, class _Size> 2059783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) { 2064f9b2469SLouis Dionne auto __idx = __first; 207ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 2084f9b2469SLouis Dionne try { 2094f9b2469SLouis Dionne # endif 21016bf4339SArthur O'Dwyer for (; __n > 0; ++__idx, (void)--__n) 21119c6958dSA. Jiang ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType; 212ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 2134f9b2469SLouis Dionne } catch (...) { 21477a00c0dSLouis Dionne std::__destroy(__first, __idx); 2154f9b2469SLouis Dionne throw; 2164f9b2469SLouis Dionne } 2174f9b2469SLouis Dionne # endif 2183f630cffSKonstantin Varlamov 2193f630cffSKonstantin Varlamov return __idx; 2204f9b2469SLouis Dionne } 2214f9b2469SLouis Dionne 2223f630cffSKonstantin Varlamov template <class _ForwardIterator, class _Size> 2239783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) { 2243f630cffSKonstantin Varlamov using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 22577a00c0dSLouis Dionne return std::__uninitialized_default_construct_n<_ValueType>(std::move(__first), __n); 2263f630cffSKonstantin Varlamov } 2274f9b2469SLouis Dionne 228754ea6fdSKonstantin Varlamov // uninitialized_value_construct 229754ea6fdSKonstantin Varlamov 230754ea6fdSKonstantin Varlamov template <class _ValueType, class _ForwardIterator, class _Sentinel> 2319783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 2329783f28cSLouis Dionne __uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) { 2334f9b2469SLouis Dionne auto __idx = __first; 234ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 2354f9b2469SLouis Dionne try { 2364f9b2469SLouis Dionne # endif 2374f9b2469SLouis Dionne for (; __idx != __last; ++__idx) 23819c6958dSA. Jiang ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(); 239ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 2404f9b2469SLouis Dionne } catch (...) { 24177a00c0dSLouis Dionne std::__destroy(__first, __idx); 2424f9b2469SLouis Dionne throw; 2434f9b2469SLouis Dionne } 2444f9b2469SLouis Dionne # endif 245754ea6fdSKonstantin Varlamov 246754ea6fdSKonstantin Varlamov return __idx; 2474f9b2469SLouis Dionne } 2484f9b2469SLouis Dionne 249754ea6fdSKonstantin Varlamov template <class _ForwardIterator> 2509783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) { 251754ea6fdSKonstantin Varlamov using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 2529783f28cSLouis Dionne (void)std::__uninitialized_value_construct<_ValueType>(std::move(__first), std::move(__last)); 253754ea6fdSKonstantin Varlamov } 254754ea6fdSKonstantin Varlamov 255754ea6fdSKonstantin Varlamov // uninitialized_value_construct_n 256754ea6fdSKonstantin Varlamov 257754ea6fdSKonstantin Varlamov template <class _ValueType, class _ForwardIterator, class _Size> 2589783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { 2594f9b2469SLouis Dionne auto __idx = __first; 260ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 2614f9b2469SLouis Dionne try { 2624f9b2469SLouis Dionne # endif 26316bf4339SArthur O'Dwyer for (; __n > 0; ++__idx, (void)--__n) 26419c6958dSA. Jiang ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(); 265ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 2664f9b2469SLouis Dionne } catch (...) { 26777a00c0dSLouis Dionne std::__destroy(__first, __idx); 2684f9b2469SLouis Dionne throw; 2694f9b2469SLouis Dionne } 2704f9b2469SLouis Dionne # endif 271754ea6fdSKonstantin Varlamov 272754ea6fdSKonstantin Varlamov return __idx; 2734f9b2469SLouis Dionne } 2744f9b2469SLouis Dionne 275754ea6fdSKonstantin Varlamov template <class _ForwardIterator, class _Size> 2769783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { 277754ea6fdSKonstantin Varlamov using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 27877a00c0dSLouis Dionne return std::__uninitialized_value_construct_n<_ValueType>(std::move(__first), __n); 279754ea6fdSKonstantin Varlamov } 2804f9b2469SLouis Dionne 2818d23b742SKonstantin Varlamov // uninitialized_move 2828d23b742SKonstantin Varlamov 2837961fa36SLouis Dionne template <class _ValueType, 2847961fa36SLouis Dionne class _InputIterator, 2857961fa36SLouis Dionne class _Sentinel1, 2867961fa36SLouis Dionne class _ForwardIterator, 2877961fa36SLouis Dionne class _EndPredicate, 2888d23b742SKonstantin Varlamov class _IterMove> 2897961fa36SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move( 2907961fa36SLouis Dionne _InputIterator __ifirst, 2917961fa36SLouis Dionne _Sentinel1 __ilast, 2927961fa36SLouis Dionne _ForwardIterator __ofirst, 2937961fa36SLouis Dionne _EndPredicate __stop_moving, 2947961fa36SLouis Dionne _IterMove __iter_move) { 2958d23b742SKonstantin Varlamov auto __idx = __ofirst; 296ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 2974f9b2469SLouis Dionne try { 2984f9b2469SLouis Dionne # endif 2997961fa36SLouis Dionne for (; __ifirst != __ilast && !__stop_moving(__idx); ++__idx, (void)++__ifirst) { 30019c6958dSA. Jiang ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__iter_move(__ifirst)); 3018d23b742SKonstantin Varlamov } 302ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 3034f9b2469SLouis Dionne } catch (...) { 30477a00c0dSLouis Dionne std::__destroy(__ofirst, __idx); 3054f9b2469SLouis Dionne throw; 3064f9b2469SLouis Dionne } 3074f9b2469SLouis Dionne # endif 3088d23b742SKonstantin Varlamov 30977a00c0dSLouis Dionne return {std::move(__ifirst), std::move(__idx)}; 3104f9b2469SLouis Dionne } 3114f9b2469SLouis Dionne 3128d23b742SKonstantin Varlamov template <class _InputIterator, class _ForwardIterator> 3139783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 3149783f28cSLouis Dionne uninitialized_move(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIterator __ofirst) { 3158d23b742SKonstantin Varlamov using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 31677a00c0dSLouis Dionne auto __iter_move = [](auto&& __iter) -> decltype(auto) { return std::move(*__iter); }; 3178d23b742SKonstantin Varlamov 3187961fa36SLouis Dionne auto __result = std::__uninitialized_move<_ValueType>( 3197961fa36SLouis Dionne std::move(__ifirst), std::move(__ilast), std::move(__ofirst), __always_false(), __iter_move); 32077a00c0dSLouis Dionne return std::move(__result.second); 3218d23b742SKonstantin Varlamov } 3228d23b742SKonstantin Varlamov 3238d23b742SKonstantin Varlamov // uninitialized_move_n 3248d23b742SKonstantin Varlamov 3257961fa36SLouis Dionne template <class _ValueType, 3267961fa36SLouis Dionne class _InputIterator, 3277961fa36SLouis Dionne class _Size, 3287961fa36SLouis Dionne class _ForwardIterator, 3297961fa36SLouis Dionne class _EndPredicate, 3307961fa36SLouis Dionne class _IterMove> 3317961fa36SLouis Dionne inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move_n( 3327961fa36SLouis Dionne _InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _EndPredicate __stop_moving, _IterMove __iter_move) { 3338d23b742SKonstantin Varlamov auto __idx = __ofirst; 334ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 3354f9b2469SLouis Dionne try { 3364f9b2469SLouis Dionne # endif 3377961fa36SLouis Dionne for (; __n > 0 && !__stop_moving(__idx); ++__idx, (void)++__ifirst, --__n) 33819c6958dSA. Jiang ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__iter_move(__ifirst)); 339ba87515fSNikolas Klauser # if _LIBCPP_HAS_EXCEPTIONS 3404f9b2469SLouis Dionne } catch (...) { 34177a00c0dSLouis Dionne std::__destroy(__ofirst, __idx); 3424f9b2469SLouis Dionne throw; 3434f9b2469SLouis Dionne } 3444f9b2469SLouis Dionne # endif 3458d23b742SKonstantin Varlamov 34677a00c0dSLouis Dionne return {std::move(__ifirst), std::move(__idx)}; 3478d23b742SKonstantin Varlamov } 3488d23b742SKonstantin Varlamov 3498d23b742SKonstantin Varlamov template <class _InputIterator, class _Size, class _ForwardIterator> 3508d23b742SKonstantin Varlamov inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> 3518d23b742SKonstantin Varlamov uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) { 3528d23b742SKonstantin Varlamov using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; 35377a00c0dSLouis Dionne auto __iter_move = [](auto&& __iter) -> decltype(auto) { return std::move(*__iter); }; 3548d23b742SKonstantin Varlamov 3557961fa36SLouis Dionne return std::__uninitialized_move_n<_ValueType>( 3567961fa36SLouis Dionne std::move(__ifirst), __n, std::move(__ofirst), __always_false(), __iter_move); 3574f9b2469SLouis Dionne } 3584f9b2469SLouis Dionne 359f4fb72e6SNikolas Klauser // TODO: Rewrite this to iterate left to right and use reverse_iterators when calling 360e27a122bSLouis Dionne // Destroys every element in the range [first, last) FROM RIGHT TO LEFT using allocator 361e27a122bSLouis Dionne // destruction. If elements are themselves C-style arrays, they are recursively destroyed 362e27a122bSLouis Dionne // in the same manner. 363e27a122bSLouis Dionne // 364e27a122bSLouis Dionne // This function assumes that destructors do not throw, and that the allocator is bound to 365e27a122bSLouis Dionne // the correct type. 3669783f28cSLouis Dionne template <class _Alloc, 3679783f28cSLouis Dionne class _BidirIter, 36876a24727SNikolas Klauser __enable_if_t<__has_bidirectional_iterator_category<_BidirIter>::value, int> = 0> 3699783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr void 3709783f28cSLouis Dionne __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter __first, _BidirIter __last) noexcept { 371e27a122bSLouis Dionne using _ValueType = typename iterator_traits<_BidirIter>::value_type; 372e27a122bSLouis Dionne static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _ValueType>, 373e27a122bSLouis Dionne "The allocator should already be rebound to the correct type"); 374e27a122bSLouis Dionne 375e27a122bSLouis Dionne if (__first == __last) 376e27a122bSLouis Dionne return; 377e27a122bSLouis Dionne 378e27a122bSLouis Dionne if constexpr (is_array_v<_ValueType>) { 37930213e99SNikolas Klauser static_assert(!__is_unbounded_array_v<_ValueType>, 380e27a122bSLouis Dionne "arrays of unbounded arrays don't exist, but if they did we would mess up here"); 381e27a122bSLouis Dionne 382e27a122bSLouis Dionne using _Element = remove_extent_t<_ValueType>; 383e27a122bSLouis Dionne __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc); 384e27a122bSLouis Dionne do { 385e27a122bSLouis Dionne --__last; 386e27a122bSLouis Dionne decltype(auto) __array = *__last; 387e27a122bSLouis Dionne std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + extent_v<_ValueType>); 388e27a122bSLouis Dionne } while (__last != __first); 389e27a122bSLouis Dionne } else { 390e27a122bSLouis Dionne do { 391e27a122bSLouis Dionne --__last; 392e27a122bSLouis Dionne allocator_traits<_Alloc>::destroy(__alloc, std::addressof(*__last)); 393e27a122bSLouis Dionne } while (__last != __first); 394e27a122bSLouis Dionne } 395e27a122bSLouis Dionne } 396e27a122bSLouis Dionne 397e27a122bSLouis Dionne // Constructs the object at the given location using the allocator's construct method. 398e27a122bSLouis Dionne // 399e27a122bSLouis Dionne // If the object being constructed is an array, each element of the array is allocator-constructed, 400e27a122bSLouis Dionne // recursively. If an exception is thrown during the construction of an array, the initialized 401e27a122bSLouis Dionne // elements are destroyed in reverse order of initialization using allocator destruction. 402e27a122bSLouis Dionne // 403e27a122bSLouis Dionne // This function assumes that the allocator is bound to the correct type. 404e27a122bSLouis Dionne template <class _Alloc, class _Tp> 4059783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc) { 406e27a122bSLouis Dionne static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>, 407e27a122bSLouis Dionne "The allocator should already be rebound to the correct type"); 408e27a122bSLouis Dionne 409e27a122bSLouis Dionne if constexpr (is_array_v<_Tp>) { 410e27a122bSLouis Dionne using _Element = remove_extent_t<_Tp>; 411e27a122bSLouis Dionne __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc); 412e27a122bSLouis Dionne size_t __i = 0; 413e27a122bSLouis Dionne _Tp& __array = *__loc; 414e27a122bSLouis Dionne 415e27a122bSLouis Dionne // If an exception is thrown, destroy what we have constructed so far in reverse order. 4161a17739dSNikolas Klauser auto __guard = std::__make_exception_guard([&]() { 4177458908fSNikolas Klauser std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); 4187458908fSNikolas Klauser }); 4197458908fSNikolas Klauser 420e27a122bSLouis Dionne for (; __i != extent_v<_Tp>; ++__i) { 421ba43f3e8SNikolas Klauser std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i])); 422e27a122bSLouis Dionne } 423e27a122bSLouis Dionne __guard.__complete(); 424e27a122bSLouis Dionne } else { 425e27a122bSLouis Dionne allocator_traits<_Alloc>::construct(__alloc, __loc); 426e27a122bSLouis Dionne } 427e27a122bSLouis Dionne } 428e27a122bSLouis Dionne 429e27a122bSLouis Dionne // Constructs the object at the given location using the allocator's construct method, passing along 430e27a122bSLouis Dionne // the provided argument. 431e27a122bSLouis Dionne // 432e27a122bSLouis Dionne // If the object being constructed is an array, the argument is also assumed to be an array. Each 433e27a122bSLouis Dionne // each element of the array being constructed is allocator-constructed from the corresponding 434e27a122bSLouis Dionne // element of the argument array. If an exception is thrown during the construction of an array, 435e27a122bSLouis Dionne // the initialized elements are destroyed in reverse order of initialization using allocator 436e27a122bSLouis Dionne // destruction. 437e27a122bSLouis Dionne // 438e27a122bSLouis Dionne // This function assumes that the allocator is bound to the correct type. 439e27a122bSLouis Dionne template <class _Alloc, class _Tp, class _Arg> 4409783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr void 4419783f28cSLouis Dionne __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) { 442e27a122bSLouis Dionne static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>, 443e27a122bSLouis Dionne "The allocator should already be rebound to the correct type"); 444e27a122bSLouis Dionne 445e27a122bSLouis Dionne if constexpr (is_array_v<_Tp>) { 446e27a122bSLouis Dionne static_assert(is_array_v<_Arg>, 447ba43f3e8SNikolas Klauser "Provided non-array initialization argument to __allocator_construct_at_multidimensional when " 448e27a122bSLouis Dionne "trying to construct an array."); 449e27a122bSLouis Dionne 450e27a122bSLouis Dionne using _Element = remove_extent_t<_Tp>; 451e27a122bSLouis Dionne __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc); 452e27a122bSLouis Dionne size_t __i = 0; 453e27a122bSLouis Dionne _Tp& __array = *__loc; 454e27a122bSLouis Dionne 455e27a122bSLouis Dionne // If an exception is thrown, destroy what we have constructed so far in reverse order. 4561a17739dSNikolas Klauser auto __guard = std::__make_exception_guard([&]() { 4577458908fSNikolas Klauser std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); 4587458908fSNikolas Klauser }); 459e27a122bSLouis Dionne for (; __i != extent_v<_Tp>; ++__i) { 460ba43f3e8SNikolas Klauser std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]), __arg[__i]); 461e27a122bSLouis Dionne } 462e27a122bSLouis Dionne __guard.__complete(); 463e27a122bSLouis Dionne } else { 464e27a122bSLouis Dionne allocator_traits<_Alloc>::construct(__alloc, __loc, __arg); 465e27a122bSLouis Dionne } 466e27a122bSLouis Dionne } 467e27a122bSLouis Dionne 468e27a122bSLouis Dionne // Given a range starting at it and containing n elements, initializes each element in the 469e27a122bSLouis Dionne // range from left to right using the construct method of the allocator (rebound to the 470e27a122bSLouis Dionne // correct type). 471e27a122bSLouis Dionne // 472e27a122bSLouis Dionne // If an exception is thrown, the initialized elements are destroyed in reverse order of 473e27a122bSLouis Dionne // initialization using allocator_traits destruction. If the elements in the range are C-style 474e27a122bSLouis Dionne // arrays, they are initialized element-wise using allocator construction, and recursively so. 4759783f28cSLouis Dionne template <class _Alloc, 4769783f28cSLouis Dionne class _BidirIter, 4779783f28cSLouis Dionne class _Tp, 4789783f28cSLouis Dionne class _Size = typename iterator_traits<_BidirIter>::difference_type> 479ba43f3e8SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr void 480ba43f3e8SNikolas Klauser __uninitialized_allocator_fill_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) { 481e27a122bSLouis Dionne using _ValueType = typename iterator_traits<_BidirIter>::value_type; 482e27a122bSLouis Dionne __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc); 483e27a122bSLouis Dionne _BidirIter __begin = __it; 484e27a122bSLouis Dionne 485e27a122bSLouis Dionne // If an exception is thrown, destroy what we have constructed so far in reverse order. 4869783f28cSLouis Dionne auto __guard = 4879783f28cSLouis Dionne std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); 488e27a122bSLouis Dionne for (; __n != 0; --__n, ++__it) { 489ba43f3e8SNikolas Klauser std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it), __value); 490e27a122bSLouis Dionne } 491e27a122bSLouis Dionne __guard.__complete(); 492e27a122bSLouis Dionne } 493e27a122bSLouis Dionne 494ba43f3e8SNikolas Klauser // Same as __uninitialized_allocator_fill_n_multidimensional, but doesn't pass any initialization argument 495e27a122bSLouis Dionne // to the allocator's construct method, which results in value initialization. 496e27a122bSLouis Dionne template <class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type> 497ba43f3e8SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr void 498ba43f3e8SNikolas Klauser __uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n) { 499e27a122bSLouis Dionne using _ValueType = typename iterator_traits<_BidirIter>::value_type; 500e27a122bSLouis Dionne __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc); 501e27a122bSLouis Dionne _BidirIter __begin = __it; 502e27a122bSLouis Dionne 503e27a122bSLouis Dionne // If an exception is thrown, destroy what we have constructed so far in reverse order. 5049783f28cSLouis Dionne auto __guard = 5059783f28cSLouis Dionne std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); 506e27a122bSLouis Dionne for (; __n != 0; --__n, ++__it) { 507ba43f3e8SNikolas Klauser std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it)); 508e27a122bSLouis Dionne } 509e27a122bSLouis Dionne __guard.__complete(); 510e27a122bSLouis Dionne } 511e27a122bSLouis Dionne 5124f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 17 513e27a122bSLouis Dionne 514f4fb72e6SNikolas Klauser // Destroy all elements in [__first, __last) from left to right using allocator destruction. 515f4fb72e6SNikolas Klauser template <class _Alloc, class _Iter, class _Sent> 5165146b57bSNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 517f4fb72e6SNikolas Klauser __allocator_destroy(_Alloc& __alloc, _Iter __first, _Sent __last) { 518f4fb72e6SNikolas Klauser for (; __first != __last; ++__first) 519f4fb72e6SNikolas Klauser allocator_traits<_Alloc>::destroy(__alloc, std::__to_address(__first)); 520f4fb72e6SNikolas Klauser } 521f4fb72e6SNikolas Klauser 522f4fb72e6SNikolas Klauser template <class _Alloc, class _Iter> 523f4fb72e6SNikolas Klauser class _AllocatorDestroyRangeReverse { 524f4fb72e6SNikolas Klauser public: 5255146b57bSNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 52698d3d5b5SNikolas Klauser _AllocatorDestroyRangeReverse(_Alloc& __alloc, _Iter& __first, _Iter& __last) 527f4fb72e6SNikolas Klauser : __alloc_(__alloc), __first_(__first), __last_(__last) {} 528f4fb72e6SNikolas Klauser 5295146b57bSNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void operator()() const { 530f4fb72e6SNikolas Klauser std::__allocator_destroy(__alloc_, std::reverse_iterator<_Iter>(__last_), std::reverse_iterator<_Iter>(__first_)); 531f4fb72e6SNikolas Klauser } 532f4fb72e6SNikolas Klauser 533f4fb72e6SNikolas Klauser private: 534f4fb72e6SNikolas Klauser _Alloc& __alloc_; 535f4fb72e6SNikolas Klauser _Iter& __first_; 536f4fb72e6SNikolas Klauser _Iter& __last_; 537f4fb72e6SNikolas Klauser }; 538f4fb72e6SNikolas Klauser 539f4fb72e6SNikolas Klauser // Copy-construct [__first1, __last1) in [__first2, __first2 + N), where N is distance(__first1, __last1). 540f4fb72e6SNikolas Klauser // 541f4fb72e6SNikolas Klauser // The caller has to ensure that __first2 can hold at least N uninitialized elements. If an exception is thrown the 542f4fb72e6SNikolas Klauser // already copied elements are destroyed in reverse order of their construction. 543f4fb72e6SNikolas Klauser template <class _Alloc, class _Iter1, class _Sent1, class _Iter2> 5445146b57bSNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 54563a2b206SAdityaK __uninitialized_allocator_copy_impl(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { 546f4fb72e6SNikolas Klauser auto __destruct_first = __first2; 5477458908fSNikolas Klauser auto __guard = 5487458908fSNikolas Klauser std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); 549f4fb72e6SNikolas Klauser while (__first1 != __last1) { 550f4fb72e6SNikolas Klauser allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), *__first1); 551f4fb72e6SNikolas Klauser ++__first1; 552f4fb72e6SNikolas Klauser ++__first2; 553f4fb72e6SNikolas Klauser } 5547458908fSNikolas Klauser __guard.__complete(); 555f4fb72e6SNikolas Klauser return __first2; 556f4fb72e6SNikolas Klauser } 557f4fb72e6SNikolas Klauser 558f4fb72e6SNikolas Klauser template <class _Alloc, class _Type> 559f4fb72e6SNikolas Klauser struct __allocator_has_trivial_copy_construct : _Not<__has_construct<_Alloc, _Type*, const _Type&> > {}; 560f4fb72e6SNikolas Klauser 561f4fb72e6SNikolas Klauser template <class _Type> 562f4fb72e6SNikolas Klauser struct __allocator_has_trivial_copy_construct<allocator<_Type>, _Type> : true_type {}; 563f4fb72e6SNikolas Klauser 564f4fb72e6SNikolas Klauser template <class _Alloc, 56563a2b206SAdityaK class _In, 56663a2b206SAdityaK class _Out, 56785da39deSNikolas Klauser __enable_if_t<is_trivially_copy_constructible<_In>::value && is_trivially_copy_assignable<_In>::value && 5688100aa4cSAdityaK is_same<__remove_const_t<_In>, __remove_const_t<_Out> >::value && 56985da39deSNikolas Klauser __allocator_has_trivial_copy_construct<_Alloc, _In>::value, 57076a24727SNikolas Klauser int> = 0> 57163a2b206SAdityaK _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Out* 57263a2b206SAdityaK __uninitialized_allocator_copy_impl(_Alloc&, _In* __first1, _In* __last1, _Out* __first2) { 573f4fb72e6SNikolas Klauser if (__libcpp_is_constant_evaluated()) { 574f4fb72e6SNikolas Klauser while (__first1 != __last1) { 575f4fb72e6SNikolas Klauser std::__construct_at(std::__to_address(__first2), *__first1); 576f4fb72e6SNikolas Klauser ++__first1; 577f4fb72e6SNikolas Klauser ++__first2; 578f4fb72e6SNikolas Klauser } 579f4fb72e6SNikolas Klauser return __first2; 580f4fb72e6SNikolas Klauser } else { 58185da39deSNikolas Klauser return std::copy(__first1, __last1, __first2); 582f4fb72e6SNikolas Klauser } 583f4fb72e6SNikolas Klauser } 584f4fb72e6SNikolas Klauser 58563a2b206SAdityaK template <class _Alloc, class _Iter1, class _Sent1, class _Iter2> 5869783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 5879783f28cSLouis Dionne __uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { 588*733a98dbSA. Jiang auto __unwrapped_range = std::__unwrap_range(std::move(__first1), std::move(__last1)); 5899783f28cSLouis Dionne auto __result = std::__uninitialized_allocator_copy_impl( 590*733a98dbSA. Jiang __alloc, std::move(__unwrapped_range.first), std::move(__unwrapped_range.second), std::__unwrap_iter(__first2)); 59163a2b206SAdityaK return std::__rewrap_iter(__first2, __result); 59263a2b206SAdityaK } 59363a2b206SAdityaK 594f4fb72e6SNikolas Klauser template <class _Alloc, class _Type> 595f4fb72e6SNikolas Klauser struct __allocator_has_trivial_move_construct : _Not<__has_construct<_Alloc, _Type*, _Type&&> > {}; 596f4fb72e6SNikolas Klauser 597f4fb72e6SNikolas Klauser template <class _Type> 598f4fb72e6SNikolas Klauser struct __allocator_has_trivial_move_construct<allocator<_Type>, _Type> : true_type {}; 599f4fb72e6SNikolas Klauser 6004e112e5cSNikolas Klauser template <class _Alloc, class _Tp> 6014e112e5cSNikolas Klauser struct __allocator_has_trivial_destroy : _Not<__has_destroy<_Alloc, _Tp*> > {}; 6024e112e5cSNikolas Klauser 6034e112e5cSNikolas Klauser template <class _Tp, class _Up> 6044e112e5cSNikolas Klauser struct __allocator_has_trivial_destroy<allocator<_Tp>, _Up> : true_type {}; 6054e112e5cSNikolas Klauser 6064e112e5cSNikolas Klauser // __uninitialized_allocator_relocate relocates the objects in [__first, __last) into __result. 6074e112e5cSNikolas Klauser // Relocation means that the objects in [__first, __last) are placed into __result as-if by move-construct and destroy, 6084e112e5cSNikolas Klauser // except that the move constructor and destructor may never be called if they are known to be equivalent to a memcpy. 6094e112e5cSNikolas Klauser // 6104e112e5cSNikolas Klauser // Preconditions: __result doesn't contain any objects and [__first, __last) contains objects 6114e112e5cSNikolas Klauser // Postconditions: __result contains the objects from [__first, __last) and 6124e112e5cSNikolas Klauser // [__first, __last) doesn't contain any objects 6134e112e5cSNikolas Klauser // 6144e112e5cSNikolas Klauser // The strong exception guarantee is provided if any of the following are true: 6156721bcfdSLouis Dionne // - is_nothrow_move_constructible<_ValueType> 6166721bcfdSLouis Dionne // - is_copy_constructible<_ValueType> 6176721bcfdSLouis Dionne // - __libcpp_is_trivially_relocatable<_ValueType> 6186721bcfdSLouis Dionne template <class _Alloc, class _ContiguousIterator> 6196721bcfdSLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __uninitialized_allocator_relocate( 6206721bcfdSLouis Dionne _Alloc& __alloc, _ContiguousIterator __first, _ContiguousIterator __last, _ContiguousIterator __result) { 6216721bcfdSLouis Dionne static_assert(__libcpp_is_contiguous_iterator<_ContiguousIterator>::value, ""); 6226721bcfdSLouis Dionne using _ValueType = typename iterator_traits<_ContiguousIterator>::value_type; 6234e112e5cSNikolas Klauser static_assert(__is_cpp17_move_insertable<_Alloc>::value, 6244e112e5cSNikolas Klauser "The specified type does not meet the requirements of Cpp17MoveInsertable"); 6256721bcfdSLouis Dionne if (__libcpp_is_constant_evaluated() || !__libcpp_is_trivially_relocatable<_ValueType>::value || 6266721bcfdSLouis Dionne !__allocator_has_trivial_move_construct<_Alloc, _ValueType>::value || 6276721bcfdSLouis Dionne !__allocator_has_trivial_destroy<_Alloc, _ValueType>::value) { 6284e112e5cSNikolas Klauser auto __destruct_first = __result; 6296721bcfdSLouis Dionne auto __guard = std::__make_exception_guard( 6306721bcfdSLouis Dionne _AllocatorDestroyRangeReverse<_Alloc, _ContiguousIterator>(__alloc, __destruct_first, __result)); 6314e112e5cSNikolas Klauser auto __iter = __first; 6324e112e5cSNikolas Klauser while (__iter != __last) { 633ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 6345c3befb9SLouis Dionne allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__result), std::move_if_noexcept(*__iter)); 6354e112e5cSNikolas Klauser #else 6365c3befb9SLouis Dionne allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__result), std::move(*__iter)); 6374e112e5cSNikolas Klauser #endif 6384e112e5cSNikolas Klauser ++__iter; 6394e112e5cSNikolas Klauser ++__result; 640f4fb72e6SNikolas Klauser } 6414e112e5cSNikolas Klauser __guard.__complete(); 6424e112e5cSNikolas Klauser std::__allocator_destroy(__alloc, __first, __last); 643f4fb72e6SNikolas Klauser } else { 64471315698Sserge-sans-paille // Casting to void* to suppress clang complaining that this is technically UB. 6456721bcfdSLouis Dionne __builtin_memcpy(static_cast<void*>(std::__to_address(__result)), 6466721bcfdSLouis Dionne std::__to_address(__first), 6476721bcfdSLouis Dionne sizeof(_ValueType) * (__last - __first)); 648f4fb72e6SNikolas Klauser } 649f4fb72e6SNikolas Klauser } 650f4fb72e6SNikolas Klauser 6514f9b2469SLouis Dionne _LIBCPP_END_NAMESPACE_STD 6524f9b2469SLouis Dionne 6537b462251SLouis Dionne _LIBCPP_POP_MACROS 6547b462251SLouis Dionne 6554f9b2469SLouis Dionne #endif // _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H 656