176d0caaeSpatrick // -*- C++ -*-
276d0caaeSpatrick //===----------------------------------------------------------------------===//
376d0caaeSpatrick //
476d0caaeSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
576d0caaeSpatrick // See https://llvm.org/LICENSE.txt for license information.
676d0caaeSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
776d0caaeSpatrick //
876d0caaeSpatrick //===----------------------------------------------------------------------===//
976d0caaeSpatrick 
1076d0caaeSpatrick #ifndef _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H
1176d0caaeSpatrick #define _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H
1276d0caaeSpatrick 
13*4bdff4beSrobert #include <__algorithm/copy.h>
14*4bdff4beSrobert #include <__algorithm/move.h>
1576d0caaeSpatrick #include <__config>
16*4bdff4beSrobert #include <__iterator/iterator_traits.h>
17*4bdff4beSrobert #include <__iterator/reverse_iterator.h>
1876d0caaeSpatrick #include <__memory/addressof.h>
19*4bdff4beSrobert #include <__memory/allocator_traits.h>
2076d0caaeSpatrick #include <__memory/construct_at.h>
21*4bdff4beSrobert #include <__memory/pointer_traits.h>
22*4bdff4beSrobert #include <__memory/voidify.h>
23*4bdff4beSrobert #include <__type_traits/extent.h>
24*4bdff4beSrobert #include <__type_traits/is_array.h>
25*4bdff4beSrobert #include <__type_traits/is_constant_evaluated.h>
26*4bdff4beSrobert #include <__type_traits/is_trivially_copy_assignable.h>
27*4bdff4beSrobert #include <__type_traits/is_trivially_copy_constructible.h>
28*4bdff4beSrobert #include <__type_traits/is_trivially_move_assignable.h>
29*4bdff4beSrobert #include <__type_traits/is_trivially_move_constructible.h>
30*4bdff4beSrobert #include <__type_traits/is_unbounded_array.h>
31*4bdff4beSrobert #include <__type_traits/negation.h>
32*4bdff4beSrobert #include <__type_traits/remove_const.h>
33*4bdff4beSrobert #include <__type_traits/remove_extent.h>
34*4bdff4beSrobert #include <__utility/exception_guard.h>
35*4bdff4beSrobert #include <__utility/move.h>
36*4bdff4beSrobert #include <__utility/pair.h>
37*4bdff4beSrobert #include <new>
3876d0caaeSpatrick 
3976d0caaeSpatrick #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
4076d0caaeSpatrick #  pragma GCC system_header
4176d0caaeSpatrick #endif
4276d0caaeSpatrick 
4376d0caaeSpatrick _LIBCPP_BEGIN_NAMESPACE_STD
4476d0caaeSpatrick 
45*4bdff4beSrobert // This is a simplified version of C++20 `unreachable_sentinel` that doesn't use concepts and thus can be used in any
46*4bdff4beSrobert // language mode.
47*4bdff4beSrobert struct __unreachable_sentinel {
48*4bdff4beSrobert   template <class _Iter>
49*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR bool operator!=(const _Iter&, __unreachable_sentinel) _NOEXCEPT {
50*4bdff4beSrobert     return true;
5176d0caaeSpatrick   }
52*4bdff4beSrobert };
53*4bdff4beSrobert 
54*4bdff4beSrobert // uninitialized_copy
55*4bdff4beSrobert 
56*4bdff4beSrobert template <class _ValueType, class _InputIterator, class _Sentinel1, class _ForwardIterator, class _Sentinel2>
57*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
__uninitialized_copy(_InputIterator __ifirst,_Sentinel1 __ilast,_ForwardIterator __ofirst,_Sentinel2 __olast)58*4bdff4beSrobert __uninitialized_copy(_InputIterator __ifirst, _Sentinel1 __ilast,
59*4bdff4beSrobert                      _ForwardIterator __ofirst, _Sentinel2 __olast) {
60*4bdff4beSrobert   _ForwardIterator __idx = __ofirst;
61*4bdff4beSrobert #ifndef _LIBCPP_NO_EXCEPTIONS
62*4bdff4beSrobert   try {
63*4bdff4beSrobert #endif
64*4bdff4beSrobert     for (; __ifirst != __ilast && __idx != __olast; ++__ifirst, (void)++__idx)
65*4bdff4beSrobert       ::new (_VSTD::__voidify(*__idx)) _ValueType(*__ifirst);
66*4bdff4beSrobert #ifndef _LIBCPP_NO_EXCEPTIONS
67*4bdff4beSrobert   } catch (...) {
68*4bdff4beSrobert     _VSTD::__destroy(__ofirst, __idx);
6976d0caaeSpatrick     throw;
7076d0caaeSpatrick   }
7176d0caaeSpatrick #endif
72*4bdff4beSrobert 
73*4bdff4beSrobert   return pair<_InputIterator, _ForwardIterator>(_VSTD::move(__ifirst), _VSTD::move(__idx));
74*4bdff4beSrobert }
75*4bdff4beSrobert 
76*4bdff4beSrobert template <class _InputIterator, class _ForwardIterator>
77*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
uninitialized_copy(_InputIterator __ifirst,_InputIterator __ilast,_ForwardIterator __ofirst)78*4bdff4beSrobert _ForwardIterator uninitialized_copy(_InputIterator __ifirst, _InputIterator __ilast,
79*4bdff4beSrobert                                     _ForwardIterator __ofirst) {
80*4bdff4beSrobert   typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
81*4bdff4beSrobert   auto __result = _VSTD::__uninitialized_copy<_ValueType>(_VSTD::move(__ifirst), _VSTD::move(__ilast),
82*4bdff4beSrobert                                                           _VSTD::move(__ofirst), __unreachable_sentinel());
83*4bdff4beSrobert   return _VSTD::move(__result.second);
84*4bdff4beSrobert }
85*4bdff4beSrobert 
86*4bdff4beSrobert // uninitialized_copy_n
87*4bdff4beSrobert 
88*4bdff4beSrobert template <class _ValueType, class _InputIterator, class _Size, class _ForwardIterator, class _Sentinel>
89*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
__uninitialized_copy_n(_InputIterator __ifirst,_Size __n,_ForwardIterator __ofirst,_Sentinel __olast)90*4bdff4beSrobert __uninitialized_copy_n(_InputIterator __ifirst, _Size __n,
91*4bdff4beSrobert                        _ForwardIterator __ofirst, _Sentinel __olast) {
92*4bdff4beSrobert   _ForwardIterator __idx = __ofirst;
93*4bdff4beSrobert #ifndef _LIBCPP_NO_EXCEPTIONS
94*4bdff4beSrobert   try {
95*4bdff4beSrobert #endif
96*4bdff4beSrobert     for (; __n > 0 && __idx != __olast; ++__ifirst, (void)++__idx, (void)--__n)
97*4bdff4beSrobert       ::new (_VSTD::__voidify(*__idx)) _ValueType(*__ifirst);
98*4bdff4beSrobert #ifndef _LIBCPP_NO_EXCEPTIONS
99*4bdff4beSrobert   } catch (...) {
100*4bdff4beSrobert     _VSTD::__destroy(__ofirst, __idx);
101*4bdff4beSrobert     throw;
102*4bdff4beSrobert   }
103*4bdff4beSrobert #endif
104*4bdff4beSrobert 
105*4bdff4beSrobert   return pair<_InputIterator, _ForwardIterator>(_VSTD::move(__ifirst), _VSTD::move(__idx));
10676d0caaeSpatrick }
10776d0caaeSpatrick 
10876d0caaeSpatrick template <class _InputIterator, class _Size, class _ForwardIterator>
uninitialized_copy_n(_InputIterator __ifirst,_Size __n,_ForwardIterator __ofirst)109*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_copy_n(_InputIterator __ifirst, _Size __n,
110*4bdff4beSrobert                                                                    _ForwardIterator __ofirst) {
111*4bdff4beSrobert   typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
112*4bdff4beSrobert   auto __result = _VSTD::__uninitialized_copy_n<_ValueType>(_VSTD::move(__ifirst), __n, _VSTD::move(__ofirst),
113*4bdff4beSrobert                                                             __unreachable_sentinel());
114*4bdff4beSrobert   return _VSTD::move(__result.second);
115*4bdff4beSrobert }
116*4bdff4beSrobert 
117*4bdff4beSrobert // uninitialized_fill
118*4bdff4beSrobert 
119*4bdff4beSrobert template <class _ValueType, class _ForwardIterator, class _Sentinel, class _Tp>
120*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
__uninitialized_fill(_ForwardIterator __first,_Sentinel __last,const _Tp & __x)121*4bdff4beSrobert _ForwardIterator __uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x)
12276d0caaeSpatrick {
123*4bdff4beSrobert     _ForwardIterator __idx = __first;
12476d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
12576d0caaeSpatrick     try
12676d0caaeSpatrick     {
12776d0caaeSpatrick #endif
128*4bdff4beSrobert         for (; __idx != __last; ++__idx)
129*4bdff4beSrobert             ::new (_VSTD::__voidify(*__idx)) _ValueType(__x);
13076d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
13176d0caaeSpatrick     }
13276d0caaeSpatrick     catch (...)
13376d0caaeSpatrick     {
134*4bdff4beSrobert         _VSTD::__destroy(__first, __idx);
13576d0caaeSpatrick         throw;
13676d0caaeSpatrick     }
13776d0caaeSpatrick #endif
138*4bdff4beSrobert 
139*4bdff4beSrobert     return __idx;
14076d0caaeSpatrick }
14176d0caaeSpatrick 
14276d0caaeSpatrick template <class _ForwardIterator, class _Tp>
143*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
uninitialized_fill(_ForwardIterator __first,_ForwardIterator __last,const _Tp & __x)144*4bdff4beSrobert void uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __x)
14576d0caaeSpatrick {
146*4bdff4beSrobert     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
147*4bdff4beSrobert     (void)_VSTD::__uninitialized_fill<_ValueType>(__first, __last, __x);
148*4bdff4beSrobert }
149*4bdff4beSrobert 
150*4bdff4beSrobert // uninitialized_fill_n
151*4bdff4beSrobert 
152*4bdff4beSrobert template <class _ValueType, class _ForwardIterator, class _Size, class _Tp>
153*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
__uninitialized_fill_n(_ForwardIterator __first,_Size __n,const _Tp & __x)154*4bdff4beSrobert _ForwardIterator __uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
155*4bdff4beSrobert {
156*4bdff4beSrobert     _ForwardIterator __idx = __first;
15776d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
15876d0caaeSpatrick     try
15976d0caaeSpatrick     {
16076d0caaeSpatrick #endif
161*4bdff4beSrobert         for (; __n > 0; ++__idx, (void) --__n)
162*4bdff4beSrobert             ::new (_VSTD::__voidify(*__idx)) _ValueType(__x);
16376d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
16476d0caaeSpatrick     }
16576d0caaeSpatrick     catch (...)
16676d0caaeSpatrick     {
167*4bdff4beSrobert         _VSTD::__destroy(__first, __idx);
16876d0caaeSpatrick         throw;
16976d0caaeSpatrick     }
17076d0caaeSpatrick #endif
171*4bdff4beSrobert 
172*4bdff4beSrobert     return __idx;
17376d0caaeSpatrick }
17476d0caaeSpatrick 
17576d0caaeSpatrick template <class _ForwardIterator, class _Size, class _Tp>
176*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
uninitialized_fill_n(_ForwardIterator __first,_Size __n,const _Tp & __x)177*4bdff4beSrobert _ForwardIterator uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
17876d0caaeSpatrick {
179*4bdff4beSrobert     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
180*4bdff4beSrobert     return _VSTD::__uninitialized_fill_n<_ValueType>(__first, __n, __x);
18176d0caaeSpatrick }
18276d0caaeSpatrick 
18376d0caaeSpatrick #if _LIBCPP_STD_VER > 14
18476d0caaeSpatrick 
185*4bdff4beSrobert // uninitialized_default_construct
18676d0caaeSpatrick 
187*4bdff4beSrobert template <class _ValueType, class _ForwardIterator, class _Sentinel>
188*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
__uninitialized_default_construct(_ForwardIterator __first,_Sentinel __last)189*4bdff4beSrobert _ForwardIterator __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) {
190*4bdff4beSrobert     auto __idx = __first;
191*4bdff4beSrobert #ifndef _LIBCPP_NO_EXCEPTIONS
192*4bdff4beSrobert     try {
193*4bdff4beSrobert #endif
194*4bdff4beSrobert     for (; __idx != __last; ++__idx)
195*4bdff4beSrobert         ::new (_VSTD::__voidify(*__idx)) _ValueType;
196*4bdff4beSrobert #ifndef _LIBCPP_NO_EXCEPTIONS
197*4bdff4beSrobert     } catch (...) {
198*4bdff4beSrobert         _VSTD::__destroy(__first, __idx);
199*4bdff4beSrobert         throw;
200*4bdff4beSrobert     }
201*4bdff4beSrobert #endif
202*4bdff4beSrobert 
203*4bdff4beSrobert     return __idx;
20476d0caaeSpatrick }
20576d0caaeSpatrick 
20676d0caaeSpatrick template <class _ForwardIterator>
207*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
uninitialized_default_construct(_ForwardIterator __first,_ForwardIterator __last)20876d0caaeSpatrick void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) {
209*4bdff4beSrobert     using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
210*4bdff4beSrobert     (void)_VSTD::__uninitialized_default_construct<_ValueType>(
211*4bdff4beSrobert         _VSTD::move(__first), _VSTD::move(__last));
212*4bdff4beSrobert }
213*4bdff4beSrobert 
214*4bdff4beSrobert // uninitialized_default_construct_n
215*4bdff4beSrobert 
216*4bdff4beSrobert template <class _ValueType, class _ForwardIterator, class _Size>
217*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
__uninitialized_default_construct_n(_ForwardIterator __first,_Size __n)218*4bdff4beSrobert _ForwardIterator __uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
219*4bdff4beSrobert     auto __idx = __first;
220*4bdff4beSrobert #ifndef _LIBCPP_NO_EXCEPTIONS
221*4bdff4beSrobert     try {
222*4bdff4beSrobert #endif
223*4bdff4beSrobert     for (; __n > 0; ++__idx, (void) --__n)
224*4bdff4beSrobert         ::new (_VSTD::__voidify(*__idx)) _ValueType;
225*4bdff4beSrobert #ifndef _LIBCPP_NO_EXCEPTIONS
226*4bdff4beSrobert     } catch (...) {
227*4bdff4beSrobert         _VSTD::__destroy(__first, __idx);
228*4bdff4beSrobert         throw;
229*4bdff4beSrobert     }
230*4bdff4beSrobert #endif
231*4bdff4beSrobert 
232*4bdff4beSrobert     return __idx;
233*4bdff4beSrobert }
234*4bdff4beSrobert 
235*4bdff4beSrobert template <class _ForwardIterator, class _Size>
236*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
uninitialized_default_construct_n(_ForwardIterator __first,_Size __n)237*4bdff4beSrobert _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
238*4bdff4beSrobert     using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
239*4bdff4beSrobert     return _VSTD::__uninitialized_default_construct_n<_ValueType>(_VSTD::move(__first), __n);
240*4bdff4beSrobert }
241*4bdff4beSrobert 
242*4bdff4beSrobert // uninitialized_value_construct
243*4bdff4beSrobert 
244*4bdff4beSrobert template <class _ValueType, class _ForwardIterator, class _Sentinel>
245*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
__uninitialized_value_construct(_ForwardIterator __first,_Sentinel __last)246*4bdff4beSrobert _ForwardIterator __uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) {
24776d0caaeSpatrick     auto __idx = __first;
24876d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
24976d0caaeSpatrick     try {
25076d0caaeSpatrick #endif
25176d0caaeSpatrick     for (; __idx != __last; ++__idx)
252*4bdff4beSrobert         ::new (_VSTD::__voidify(*__idx)) _ValueType();
25376d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
25476d0caaeSpatrick     } catch (...) {
255*4bdff4beSrobert         _VSTD::__destroy(__first, __idx);
25676d0caaeSpatrick         throw;
25776d0caaeSpatrick     }
25876d0caaeSpatrick #endif
25976d0caaeSpatrick 
26076d0caaeSpatrick     return __idx;
26176d0caaeSpatrick }
26276d0caaeSpatrick 
26376d0caaeSpatrick template <class _ForwardIterator>
264*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
uninitialized_value_construct(_ForwardIterator __first,_ForwardIterator __last)26576d0caaeSpatrick void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) {
266*4bdff4beSrobert     using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
267*4bdff4beSrobert     (void)_VSTD::__uninitialized_value_construct<_ValueType>(
268*4bdff4beSrobert         _VSTD::move(__first), _VSTD::move(__last));
269*4bdff4beSrobert }
270*4bdff4beSrobert 
271*4bdff4beSrobert // uninitialized_value_construct_n
272*4bdff4beSrobert 
273*4bdff4beSrobert template <class _ValueType, class _ForwardIterator, class _Size>
274*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
__uninitialized_value_construct_n(_ForwardIterator __first,_Size __n)275*4bdff4beSrobert _ForwardIterator __uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
27676d0caaeSpatrick     auto __idx = __first;
27776d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
27876d0caaeSpatrick     try {
27976d0caaeSpatrick #endif
280*4bdff4beSrobert     for (; __n > 0; ++__idx, (void) --__n)
281*4bdff4beSrobert         ::new (_VSTD::__voidify(*__idx)) _ValueType();
28276d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
28376d0caaeSpatrick     } catch (...) {
284*4bdff4beSrobert         _VSTD::__destroy(__first, __idx);
28576d0caaeSpatrick         throw;
28676d0caaeSpatrick     }
28776d0caaeSpatrick #endif
288*4bdff4beSrobert 
289*4bdff4beSrobert     return __idx;
29076d0caaeSpatrick }
29176d0caaeSpatrick 
29276d0caaeSpatrick template <class _ForwardIterator, class _Size>
293*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI
uninitialized_value_construct_n(_ForwardIterator __first,_Size __n)29476d0caaeSpatrick _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
295*4bdff4beSrobert     using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
296*4bdff4beSrobert     return std::__uninitialized_value_construct_n<_ValueType>(_VSTD::move(__first), __n);
297*4bdff4beSrobert }
298*4bdff4beSrobert 
299*4bdff4beSrobert // uninitialized_move
300*4bdff4beSrobert 
301*4bdff4beSrobert template <class _ValueType, class _InputIterator, class _Sentinel1, class _ForwardIterator, class _Sentinel2,
302*4bdff4beSrobert           class _IterMove>
303*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
__uninitialized_move(_InputIterator __ifirst,_Sentinel1 __ilast,_ForwardIterator __ofirst,_Sentinel2 __olast,_IterMove __iter_move)304*4bdff4beSrobert __uninitialized_move(_InputIterator __ifirst, _Sentinel1 __ilast,
305*4bdff4beSrobert                      _ForwardIterator __ofirst, _Sentinel2 __olast, _IterMove __iter_move) {
306*4bdff4beSrobert   auto __idx = __ofirst;
30776d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
30876d0caaeSpatrick   try {
30976d0caaeSpatrick #endif
310*4bdff4beSrobert     for (; __ifirst != __ilast && __idx != __olast; ++__idx, (void)++__ifirst) {
311*4bdff4beSrobert       ::new (_VSTD::__voidify(*__idx)) _ValueType(__iter_move(__ifirst));
312*4bdff4beSrobert     }
31376d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
31476d0caaeSpatrick   } catch (...) {
315*4bdff4beSrobert     _VSTD::__destroy(__ofirst, __idx);
31676d0caaeSpatrick     throw;
31776d0caaeSpatrick   }
31876d0caaeSpatrick #endif
319*4bdff4beSrobert 
320*4bdff4beSrobert   return {_VSTD::move(__ifirst), _VSTD::move(__idx)};
32176d0caaeSpatrick }
32276d0caaeSpatrick 
323*4bdff4beSrobert template <class _InputIterator, class _ForwardIterator>
uninitialized_move(_InputIterator __ifirst,_InputIterator __ilast,_ForwardIterator __ofirst)324*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_move(_InputIterator __ifirst, _InputIterator __ilast,
325*4bdff4beSrobert                                                                  _ForwardIterator __ofirst) {
326*4bdff4beSrobert   using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
327*4bdff4beSrobert   auto __iter_move = [](auto&& __iter) -> decltype(auto) { return _VSTD::move(*__iter); };
32876d0caaeSpatrick 
329*4bdff4beSrobert   auto __result = _VSTD::__uninitialized_move<_ValueType>(_VSTD::move(__ifirst), _VSTD::move(__ilast),
330*4bdff4beSrobert                                                           _VSTD::move(__ofirst), __unreachable_sentinel(), __iter_move);
331*4bdff4beSrobert   return _VSTD::move(__result.second);
332*4bdff4beSrobert }
333*4bdff4beSrobert 
334*4bdff4beSrobert // uninitialized_move_n
335*4bdff4beSrobert 
336*4bdff4beSrobert template <class _ValueType, class _InputIterator, class _Size, class _ForwardIterator, class _Sentinel, class _IterMove>
337*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
__uninitialized_move_n(_InputIterator __ifirst,_Size __n,_ForwardIterator __ofirst,_Sentinel __olast,_IterMove __iter_move)338*4bdff4beSrobert __uninitialized_move_n(_InputIterator __ifirst, _Size __n,
339*4bdff4beSrobert                        _ForwardIterator __ofirst, _Sentinel __olast, _IterMove __iter_move) {
340*4bdff4beSrobert   auto __idx = __ofirst;
34176d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
34276d0caaeSpatrick   try {
34376d0caaeSpatrick #endif
344*4bdff4beSrobert     for (; __n > 0 && __idx != __olast; ++__idx, (void)++__ifirst, --__n)
345*4bdff4beSrobert       ::new (_VSTD::__voidify(*__idx)) _ValueType(__iter_move(__ifirst));
34676d0caaeSpatrick #ifndef _LIBCPP_NO_EXCEPTIONS
34776d0caaeSpatrick   } catch (...) {
348*4bdff4beSrobert     _VSTD::__destroy(__ofirst, __idx);
34976d0caaeSpatrick     throw;
35076d0caaeSpatrick   }
35176d0caaeSpatrick #endif
352*4bdff4beSrobert 
353*4bdff4beSrobert   return {_VSTD::move(__ifirst), _VSTD::move(__idx)};
35476d0caaeSpatrick }
35576d0caaeSpatrick 
356*4bdff4beSrobert template <class _InputIterator, class _Size, class _ForwardIterator>
357*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
uninitialized_move_n(_InputIterator __ifirst,_Size __n,_ForwardIterator __ofirst)358*4bdff4beSrobert uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) {
359*4bdff4beSrobert   using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
360*4bdff4beSrobert   auto __iter_move = [](auto&& __iter) -> decltype(auto) { return _VSTD::move(*__iter); };
361*4bdff4beSrobert 
362*4bdff4beSrobert   return _VSTD::__uninitialized_move_n<_ValueType>(_VSTD::move(__ifirst), __n, _VSTD::move(__ofirst),
363*4bdff4beSrobert                                                    __unreachable_sentinel(), __iter_move);
36476d0caaeSpatrick }
365*4bdff4beSrobert 
366*4bdff4beSrobert // TODO: Rewrite this to iterate left to right and use reverse_iterators when calling
367*4bdff4beSrobert // Destroys every element in the range [first, last) FROM RIGHT TO LEFT using allocator
368*4bdff4beSrobert // destruction. If elements are themselves C-style arrays, they are recursively destroyed
369*4bdff4beSrobert // in the same manner.
370*4bdff4beSrobert //
371*4bdff4beSrobert // This function assumes that destructors do not throw, and that the allocator is bound to
372*4bdff4beSrobert // the correct type.
373*4bdff4beSrobert template<class _Alloc, class _BidirIter, class = __enable_if_t<
374*4bdff4beSrobert     __is_cpp17_bidirectional_iterator<_BidirIter>::value
375*4bdff4beSrobert >>
376*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
__allocator_destroy_multidimensional(_Alloc & __alloc,_BidirIter __first,_BidirIter __last)377*4bdff4beSrobert constexpr void __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter __first, _BidirIter __last) noexcept {
378*4bdff4beSrobert     using _ValueType = typename iterator_traits<_BidirIter>::value_type;
379*4bdff4beSrobert     static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _ValueType>,
380*4bdff4beSrobert         "The allocator should already be rebound to the correct type");
381*4bdff4beSrobert 
382*4bdff4beSrobert     if (__first == __last)
383*4bdff4beSrobert         return;
384*4bdff4beSrobert 
385*4bdff4beSrobert     if constexpr (is_array_v<_ValueType>) {
386*4bdff4beSrobert         static_assert(!__libcpp_is_unbounded_array<_ValueType>::value,
387*4bdff4beSrobert             "arrays of unbounded arrays don't exist, but if they did we would mess up here");
388*4bdff4beSrobert 
389*4bdff4beSrobert         using _Element = remove_extent_t<_ValueType>;
390*4bdff4beSrobert         __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc);
391*4bdff4beSrobert         do {
392*4bdff4beSrobert             --__last;
393*4bdff4beSrobert             decltype(auto) __array = *__last;
394*4bdff4beSrobert             std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + extent_v<_ValueType>);
395*4bdff4beSrobert         } while (__last != __first);
396*4bdff4beSrobert     } else {
397*4bdff4beSrobert         do {
398*4bdff4beSrobert             --__last;
399*4bdff4beSrobert             allocator_traits<_Alloc>::destroy(__alloc, std::addressof(*__last));
400*4bdff4beSrobert         } while (__last != __first);
401*4bdff4beSrobert     }
402*4bdff4beSrobert }
403*4bdff4beSrobert 
404*4bdff4beSrobert // Constructs the object at the given location using the allocator's construct method.
405*4bdff4beSrobert //
406*4bdff4beSrobert // If the object being constructed is an array, each element of the array is allocator-constructed,
407*4bdff4beSrobert // recursively. If an exception is thrown during the construction of an array, the initialized
408*4bdff4beSrobert // elements are destroyed in reverse order of initialization using allocator destruction.
409*4bdff4beSrobert //
410*4bdff4beSrobert // This function assumes that the allocator is bound to the correct type.
411*4bdff4beSrobert template<class _Alloc, class _Tp>
412*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
__allocator_construct_at_multidimensional(_Alloc & __alloc,_Tp * __loc)413*4bdff4beSrobert constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc) {
414*4bdff4beSrobert     static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>,
415*4bdff4beSrobert         "The allocator should already be rebound to the correct type");
416*4bdff4beSrobert 
417*4bdff4beSrobert     if constexpr (is_array_v<_Tp>) {
418*4bdff4beSrobert         using _Element = remove_extent_t<_Tp>;
419*4bdff4beSrobert         __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc);
420*4bdff4beSrobert         size_t __i = 0;
421*4bdff4beSrobert         _Tp& __array = *__loc;
422*4bdff4beSrobert 
423*4bdff4beSrobert         // If an exception is thrown, destroy what we have constructed so far in reverse order.
424*4bdff4beSrobert         auto __guard = std::__make_exception_guard([&]() {
425*4bdff4beSrobert           std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i);
426*4bdff4beSrobert         });
427*4bdff4beSrobert 
428*4bdff4beSrobert         for (; __i != extent_v<_Tp>; ++__i) {
429*4bdff4beSrobert             std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]));
430*4bdff4beSrobert         }
431*4bdff4beSrobert         __guard.__complete();
432*4bdff4beSrobert     } else {
433*4bdff4beSrobert         allocator_traits<_Alloc>::construct(__alloc, __loc);
434*4bdff4beSrobert     }
435*4bdff4beSrobert }
436*4bdff4beSrobert 
437*4bdff4beSrobert // Constructs the object at the given location using the allocator's construct method, passing along
438*4bdff4beSrobert // the provided argument.
439*4bdff4beSrobert //
440*4bdff4beSrobert // If the object being constructed is an array, the argument is also assumed to be an array. Each
441*4bdff4beSrobert // each element of the array being constructed is allocator-constructed from the corresponding
442*4bdff4beSrobert // element of the argument array. If an exception is thrown during the construction of an array,
443*4bdff4beSrobert // the initialized elements are destroyed in reverse order of initialization using allocator
444*4bdff4beSrobert // destruction.
445*4bdff4beSrobert //
446*4bdff4beSrobert // This function assumes that the allocator is bound to the correct type.
447*4bdff4beSrobert template<class _Alloc, class _Tp, class _Arg>
448*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
__allocator_construct_at_multidimensional(_Alloc & __alloc,_Tp * __loc,_Arg const & __arg)449*4bdff4beSrobert constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) {
450*4bdff4beSrobert     static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>,
451*4bdff4beSrobert         "The allocator should already be rebound to the correct type");
452*4bdff4beSrobert 
453*4bdff4beSrobert     if constexpr (is_array_v<_Tp>) {
454*4bdff4beSrobert         static_assert(is_array_v<_Arg>,
455*4bdff4beSrobert             "Provided non-array initialization argument to __allocator_construct_at_multidimensional when "
456*4bdff4beSrobert             "trying to construct an array.");
457*4bdff4beSrobert 
458*4bdff4beSrobert         using _Element = remove_extent_t<_Tp>;
459*4bdff4beSrobert         __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc);
460*4bdff4beSrobert         size_t __i = 0;
461*4bdff4beSrobert         _Tp& __array = *__loc;
462*4bdff4beSrobert 
463*4bdff4beSrobert         // If an exception is thrown, destroy what we have constructed so far in reverse order.
464*4bdff4beSrobert         auto __guard = std::__make_exception_guard([&]() {
465*4bdff4beSrobert           std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i);
466*4bdff4beSrobert         });
467*4bdff4beSrobert         for (; __i != extent_v<_Tp>; ++__i) {
468*4bdff4beSrobert             std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]), __arg[__i]);
469*4bdff4beSrobert         }
470*4bdff4beSrobert         __guard.__complete();
471*4bdff4beSrobert     } else {
472*4bdff4beSrobert         allocator_traits<_Alloc>::construct(__alloc, __loc, __arg);
473*4bdff4beSrobert     }
474*4bdff4beSrobert }
475*4bdff4beSrobert 
476*4bdff4beSrobert // Given a range starting at it and containing n elements, initializes each element in the
477*4bdff4beSrobert // range from left to right using the construct method of the allocator (rebound to the
478*4bdff4beSrobert // correct type).
479*4bdff4beSrobert //
480*4bdff4beSrobert // If an exception is thrown, the initialized elements are destroyed in reverse order of
481*4bdff4beSrobert // initialization using allocator_traits destruction. If the elements in the range are C-style
482*4bdff4beSrobert // arrays, they are initialized element-wise using allocator construction, and recursively so.
483*4bdff4beSrobert template<class _Alloc, class _BidirIter, class _Tp, class _Size = typename iterator_traits<_BidirIter>::difference_type>
484*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr void
__uninitialized_allocator_fill_n_multidimensional(_Alloc & __alloc,_BidirIter __it,_Size __n,_Tp const & __value)485*4bdff4beSrobert __uninitialized_allocator_fill_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) {
486*4bdff4beSrobert     using _ValueType = typename iterator_traits<_BidirIter>::value_type;
487*4bdff4beSrobert     __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc);
488*4bdff4beSrobert     _BidirIter __begin = __it;
489*4bdff4beSrobert 
490*4bdff4beSrobert     // If an exception is thrown, destroy what we have constructed so far in reverse order.
491*4bdff4beSrobert     auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
492*4bdff4beSrobert     for (; __n != 0; --__n, ++__it) {
493*4bdff4beSrobert         std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it), __value);
494*4bdff4beSrobert     }
495*4bdff4beSrobert     __guard.__complete();
496*4bdff4beSrobert }
497*4bdff4beSrobert 
498*4bdff4beSrobert // Same as __uninitialized_allocator_fill_n_multidimensional, but doesn't pass any initialization argument
499*4bdff4beSrobert // to the allocator's construct method, which results in value initialization.
500*4bdff4beSrobert template <class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type>
501*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr void
__uninitialized_allocator_value_construct_n_multidimensional(_Alloc & __alloc,_BidirIter __it,_Size __n)502*4bdff4beSrobert __uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n) {
503*4bdff4beSrobert     using _ValueType = typename iterator_traits<_BidirIter>::value_type;
504*4bdff4beSrobert     __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc);
505*4bdff4beSrobert     _BidirIter __begin = __it;
506*4bdff4beSrobert 
507*4bdff4beSrobert     // If an exception is thrown, destroy what we have constructed so far in reverse order.
508*4bdff4beSrobert     auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
509*4bdff4beSrobert     for (; __n != 0; --__n, ++__it) {
510*4bdff4beSrobert         std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it));
511*4bdff4beSrobert     }
512*4bdff4beSrobert     __guard.__complete();
51376d0caaeSpatrick }
51476d0caaeSpatrick 
51576d0caaeSpatrick #endif // _LIBCPP_STD_VER > 14
51676d0caaeSpatrick 
517*4bdff4beSrobert // Destroy all elements in [__first, __last) from left to right using allocator destruction.
518*4bdff4beSrobert template <class _Alloc, class _Iter, class _Sent>
519*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
__allocator_destroy(_Alloc & __alloc,_Iter __first,_Sent __last)520*4bdff4beSrobert __allocator_destroy(_Alloc& __alloc, _Iter __first, _Sent __last) {
521*4bdff4beSrobert   for (; __first != __last; ++__first)
522*4bdff4beSrobert      allocator_traits<_Alloc>::destroy(__alloc, std::__to_address(__first));
523*4bdff4beSrobert }
52476d0caaeSpatrick 
525*4bdff4beSrobert template <class _Alloc, class _Iter>
526*4bdff4beSrobert class _AllocatorDestroyRangeReverse {
527*4bdff4beSrobert public:
528*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
_AllocatorDestroyRangeReverse(_Alloc & __alloc,_Iter & __first,_Iter & __last)529*4bdff4beSrobert   _AllocatorDestroyRangeReverse(_Alloc& __alloc, _Iter& __first, _Iter& __last)
530*4bdff4beSrobert       : __alloc_(__alloc), __first_(__first), __last_(__last) {}
531*4bdff4beSrobert 
operator()532*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void operator()() const {
533*4bdff4beSrobert     std::__allocator_destroy(__alloc_, std::reverse_iterator<_Iter>(__last_), std::reverse_iterator<_Iter>(__first_));
534*4bdff4beSrobert   }
535*4bdff4beSrobert 
536*4bdff4beSrobert private:
537*4bdff4beSrobert   _Alloc& __alloc_;
538*4bdff4beSrobert   _Iter& __first_;
539*4bdff4beSrobert   _Iter& __last_;
540*4bdff4beSrobert };
541*4bdff4beSrobert 
542*4bdff4beSrobert // Copy-construct [__first1, __last1) in [__first2, __first2 + N), where N is distance(__first1, __last1).
543*4bdff4beSrobert //
544*4bdff4beSrobert // The caller has to ensure that __first2 can hold at least N uninitialized elements. If an exception is thrown the
545*4bdff4beSrobert // already copied elements are destroyed in reverse order of their construction.
546*4bdff4beSrobert template <class _Alloc, class _Iter1, class _Sent1, class _Iter2>
547*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2
__uninitialized_allocator_copy(_Alloc & __alloc,_Iter1 __first1,_Sent1 __last1,_Iter2 __first2)548*4bdff4beSrobert __uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) {
549*4bdff4beSrobert   auto __destruct_first = __first2;
550*4bdff4beSrobert   auto __guard =
551*4bdff4beSrobert       std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2));
552*4bdff4beSrobert   while (__first1 != __last1) {
553*4bdff4beSrobert     allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), *__first1);
554*4bdff4beSrobert     ++__first1;
555*4bdff4beSrobert     ++__first2;
556*4bdff4beSrobert   }
557*4bdff4beSrobert   __guard.__complete();
558*4bdff4beSrobert   return __first2;
559*4bdff4beSrobert }
560*4bdff4beSrobert 
561*4bdff4beSrobert template <class _Alloc, class _Type>
562*4bdff4beSrobert struct __allocator_has_trivial_copy_construct : _Not<__has_construct<_Alloc, _Type*, const _Type&> > {};
563*4bdff4beSrobert 
564*4bdff4beSrobert template <class _Type>
565*4bdff4beSrobert struct __allocator_has_trivial_copy_construct<allocator<_Type>, _Type> : true_type {};
566*4bdff4beSrobert 
567*4bdff4beSrobert template <class _Alloc,
568*4bdff4beSrobert           class _Type,
569*4bdff4beSrobert           class _RawType = __remove_const_t<_Type>,
570*4bdff4beSrobert           __enable_if_t<
571*4bdff4beSrobert               // using _RawType because of the allocator<T const> extension
572*4bdff4beSrobert               is_trivially_copy_constructible<_RawType>::value && is_trivially_copy_assignable<_RawType>::value &&
573*4bdff4beSrobert               __allocator_has_trivial_copy_construct<_Alloc, _RawType>::value>* = nullptr>
574*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Type*
575*4bdff4beSrobert __uninitialized_allocator_copy(_Alloc&, const _Type* __first1, const _Type* __last1, _Type* __first2) {
576*4bdff4beSrobert   // TODO: Remove the const_cast once we drop support for std::allocator<T const>
577*4bdff4beSrobert   if (__libcpp_is_constant_evaluated()) {
578*4bdff4beSrobert     while (__first1 != __last1) {
579*4bdff4beSrobert       std::__construct_at(std::__to_address(__first2), *__first1);
580*4bdff4beSrobert       ++__first1;
581*4bdff4beSrobert       ++__first2;
582*4bdff4beSrobert     }
583*4bdff4beSrobert     return __first2;
584*4bdff4beSrobert   } else {
585*4bdff4beSrobert     return std::copy(__first1, __last1, const_cast<_RawType*>(__first2));
586*4bdff4beSrobert   }
587*4bdff4beSrobert }
588*4bdff4beSrobert 
589*4bdff4beSrobert // Move-construct the elements [__first1, __last1) into [__first2, __first2 + N)
590*4bdff4beSrobert // if the move constructor is noexcept, where N is distance(__first1, __last1).
591*4bdff4beSrobert //
592*4bdff4beSrobert // Otherwise try to copy all elements. If an exception is thrown the already copied
593*4bdff4beSrobert // elements are destroyed in reverse order of their construction.
594*4bdff4beSrobert template <class _Alloc, class _Iter1, class _Sent1, class _Iter2>
595*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 __uninitialized_allocator_move_if_noexcept(
596*4bdff4beSrobert     _Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) {
597*4bdff4beSrobert   static_assert(__is_cpp17_move_insertable<_Alloc>::value,
598*4bdff4beSrobert                 "The specified type does not meet the requirements of Cpp17MoveInsertable");
599*4bdff4beSrobert   auto __destruct_first = __first2;
600*4bdff4beSrobert   auto __guard =
601*4bdff4beSrobert       std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2));
602*4bdff4beSrobert   while (__first1 != __last1) {
603*4bdff4beSrobert #ifndef _LIBCPP_NO_EXCEPTIONS
604*4bdff4beSrobert     allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move_if_noexcept(*__first1));
605*4bdff4beSrobert #else
606*4bdff4beSrobert     allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move(*__first1));
607*4bdff4beSrobert #endif
608*4bdff4beSrobert     ++__first1;
609*4bdff4beSrobert     ++__first2;
610*4bdff4beSrobert   }
611*4bdff4beSrobert   __guard.__complete();
612*4bdff4beSrobert   return __first2;
613*4bdff4beSrobert }
614*4bdff4beSrobert 
615*4bdff4beSrobert template <class _Alloc, class _Type>
616*4bdff4beSrobert struct __allocator_has_trivial_move_construct : _Not<__has_construct<_Alloc, _Type*, _Type&&> > {};
617*4bdff4beSrobert 
618*4bdff4beSrobert template <class _Type>
619*4bdff4beSrobert struct __allocator_has_trivial_move_construct<allocator<_Type>, _Type> : true_type {};
620*4bdff4beSrobert 
621*4bdff4beSrobert #ifndef _LIBCPP_COMPILER_GCC
622*4bdff4beSrobert template <
623*4bdff4beSrobert     class _Alloc,
624*4bdff4beSrobert     class _Iter1,
625*4bdff4beSrobert     class _Iter2,
626*4bdff4beSrobert     class _Type = typename iterator_traits<_Iter1>::value_type,
627*4bdff4beSrobert     class = __enable_if_t<is_trivially_move_constructible<_Type>::value && is_trivially_move_assignable<_Type>::value &&
628*4bdff4beSrobert                           __allocator_has_trivial_move_construct<_Alloc, _Type>::value> >
629*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2
630*4bdff4beSrobert __uninitialized_allocator_move_if_noexcept(_Alloc&, _Iter1 __first1, _Iter1 __last1, _Iter2 __first2) {
631*4bdff4beSrobert   if (__libcpp_is_constant_evaluated()) {
632*4bdff4beSrobert     while (__first1 != __last1) {
633*4bdff4beSrobert       std::__construct_at(std::__to_address(__first2), std::move(*__first1));
634*4bdff4beSrobert       ++__first1;
635*4bdff4beSrobert       ++__first2;
636*4bdff4beSrobert     }
637*4bdff4beSrobert     return __first2;
638*4bdff4beSrobert   } else {
639*4bdff4beSrobert     return std::move(__first1, __last1, __first2);
640*4bdff4beSrobert   }
641*4bdff4beSrobert }
642*4bdff4beSrobert #endif // _LIBCPP_COMPILER_GCC
643*4bdff4beSrobert 
644*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
64576d0caaeSpatrick 
64676d0caaeSpatrick #endif // _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H
647