xref: /freebsd-src/contrib/llvm-project/libcxx/include/__memory/uninitialized_algorithms.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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