Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:36

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___CXX03___MEMORY_UNINITIALIZED_ALGORITHMS_H
0011 #define _LIBCPP___CXX03___MEMORY_UNINITIALIZED_ALGORITHMS_H
0012 
0013 #include <__cxx03/__algorithm/copy.h>
0014 #include <__cxx03/__algorithm/move.h>
0015 #include <__cxx03/__algorithm/unwrap_iter.h>
0016 #include <__cxx03/__algorithm/unwrap_range.h>
0017 #include <__cxx03/__config>
0018 #include <__cxx03/__iterator/iterator_traits.h>
0019 #include <__cxx03/__iterator/reverse_iterator.h>
0020 #include <__cxx03/__memory/addressof.h>
0021 #include <__cxx03/__memory/allocator_traits.h>
0022 #include <__cxx03/__memory/construct_at.h>
0023 #include <__cxx03/__memory/pointer_traits.h>
0024 #include <__cxx03/__memory/voidify.h>
0025 #include <__cxx03/__type_traits/extent.h>
0026 #include <__cxx03/__type_traits/is_array.h>
0027 #include <__cxx03/__type_traits/is_constant_evaluated.h>
0028 #include <__cxx03/__type_traits/is_trivially_assignable.h>
0029 #include <__cxx03/__type_traits/is_trivially_constructible.h>
0030 #include <__cxx03/__type_traits/is_trivially_relocatable.h>
0031 #include <__cxx03/__type_traits/is_unbounded_array.h>
0032 #include <__cxx03/__type_traits/negation.h>
0033 #include <__cxx03/__type_traits/remove_const.h>
0034 #include <__cxx03/__type_traits/remove_extent.h>
0035 #include <__cxx03/__utility/exception_guard.h>
0036 #include <__cxx03/__utility/move.h>
0037 #include <__cxx03/__utility/pair.h>
0038 #include <__cxx03/new>
0039 
0040 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0041 #  pragma GCC system_header
0042 #endif
0043 
0044 _LIBCPP_PUSH_MACROS
0045 #include <__cxx03/__undef_macros>
0046 
0047 _LIBCPP_BEGIN_NAMESPACE_STD
0048 
0049 struct __always_false {
0050   template <class... _Args>
0051   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator()(_Args&&...) const _NOEXCEPT {
0052     return false;
0053   }
0054 };
0055 
0056 // uninitialized_copy
0057 
0058 template <class _ValueType, class _InputIterator, class _Sentinel1, class _ForwardIterator, class _EndPredicate>
0059 inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_copy(
0060     _InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _EndPredicate __stop_copying) {
0061   _ForwardIterator __idx = __ofirst;
0062 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0063   try {
0064 #endif
0065     for (; __ifirst != __ilast && !__stop_copying(__idx); ++__ifirst, (void)++__idx)
0066       ::new (std::__voidify(*__idx)) _ValueType(*__ifirst);
0067 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0068   } catch (...) {
0069     std::__destroy(__ofirst, __idx);
0070     throw;
0071   }
0072 #endif
0073 
0074   return pair<_InputIterator, _ForwardIterator>(std::move(__ifirst), std::move(__idx));
0075 }
0076 
0077 template <class _InputIterator, class _ForwardIterator>
0078 _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0079 uninitialized_copy(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIterator __ofirst) {
0080   typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
0081   auto __result = std::__uninitialized_copy<_ValueType>(
0082       std::move(__ifirst), std::move(__ilast), std::move(__ofirst), __always_false());
0083   return std::move(__result.second);
0084 }
0085 
0086 // uninitialized_copy_n
0087 
0088 template <class _ValueType, class _InputIterator, class _Size, class _ForwardIterator, class _EndPredicate>
0089 inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
0090 __uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _EndPredicate __stop_copying) {
0091   _ForwardIterator __idx = __ofirst;
0092 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0093   try {
0094 #endif
0095     for (; __n > 0 && !__stop_copying(__idx); ++__ifirst, (void)++__idx, (void)--__n)
0096       ::new (std::__voidify(*__idx)) _ValueType(*__ifirst);
0097 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0098   } catch (...) {
0099     std::__destroy(__ofirst, __idx);
0100     throw;
0101   }
0102 #endif
0103 
0104   return pair<_InputIterator, _ForwardIterator>(std::move(__ifirst), std::move(__idx));
0105 }
0106 
0107 template <class _InputIterator, class _Size, class _ForwardIterator>
0108 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0109 uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) {
0110   typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
0111   auto __result =
0112       std::__uninitialized_copy_n<_ValueType>(std::move(__ifirst), __n, std::move(__ofirst), __always_false());
0113   return std::move(__result.second);
0114 }
0115 
0116 // uninitialized_fill
0117 
0118 template <class _ValueType, class _ForwardIterator, class _Sentinel, class _Tp>
0119 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0120 __uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) {
0121   _ForwardIterator __idx = __first;
0122 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0123   try {
0124 #endif
0125     for (; __idx != __last; ++__idx)
0126       ::new (std::__voidify(*__idx)) _ValueType(__x);
0127 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0128   } catch (...) {
0129     std::__destroy(__first, __idx);
0130     throw;
0131   }
0132 #endif
0133 
0134   return __idx;
0135 }
0136 
0137 template <class _ForwardIterator, class _Tp>
0138 inline _LIBCPP_HIDE_FROM_ABI void
0139 uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __x) {
0140   typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
0141   (void)std::__uninitialized_fill<_ValueType>(__first, __last, __x);
0142 }
0143 
0144 // uninitialized_fill_n
0145 
0146 template <class _ValueType, class _ForwardIterator, class _Size, class _Tp>
0147 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0148 __uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
0149   _ForwardIterator __idx = __first;
0150 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0151   try {
0152 #endif
0153     for (; __n > 0; ++__idx, (void)--__n)
0154       ::new (std::__voidify(*__idx)) _ValueType(__x);
0155 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0156   } catch (...) {
0157     std::__destroy(__first, __idx);
0158     throw;
0159   }
0160 #endif
0161 
0162   return __idx;
0163 }
0164 
0165 template <class _ForwardIterator, class _Size, class _Tp>
0166 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0167 uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
0168   typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
0169   return std::__uninitialized_fill_n<_ValueType>(__first, __n, __x);
0170 }
0171 
0172 #if _LIBCPP_STD_VER >= 17
0173 
0174 // uninitialized_default_construct
0175 
0176 template <class _ValueType, class _ForwardIterator, class _Sentinel>
0177 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0178 __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) {
0179   auto __idx = __first;
0180 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0181   try {
0182 #  endif
0183     for (; __idx != __last; ++__idx)
0184       ::new (std::__voidify(*__idx)) _ValueType;
0185 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0186   } catch (...) {
0187     std::__destroy(__first, __idx);
0188     throw;
0189   }
0190 #  endif
0191 
0192   return __idx;
0193 }
0194 
0195 template <class _ForwardIterator>
0196 inline _LIBCPP_HIDE_FROM_ABI void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) {
0197   using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
0198   (void)std::__uninitialized_default_construct<_ValueType>(std::move(__first), std::move(__last));
0199 }
0200 
0201 // uninitialized_default_construct_n
0202 
0203 template <class _ValueType, class _ForwardIterator, class _Size>
0204 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
0205   auto __idx = __first;
0206 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0207   try {
0208 #  endif
0209     for (; __n > 0; ++__idx, (void)--__n)
0210       ::new (std::__voidify(*__idx)) _ValueType;
0211 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0212   } catch (...) {
0213     std::__destroy(__first, __idx);
0214     throw;
0215   }
0216 #  endif
0217 
0218   return __idx;
0219 }
0220 
0221 template <class _ForwardIterator, class _Size>
0222 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
0223   using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
0224   return std::__uninitialized_default_construct_n<_ValueType>(std::move(__first), __n);
0225 }
0226 
0227 // uninitialized_value_construct
0228 
0229 template <class _ValueType, class _ForwardIterator, class _Sentinel>
0230 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0231 __uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) {
0232   auto __idx = __first;
0233 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0234   try {
0235 #  endif
0236     for (; __idx != __last; ++__idx)
0237       ::new (std::__voidify(*__idx)) _ValueType();
0238 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0239   } catch (...) {
0240     std::__destroy(__first, __idx);
0241     throw;
0242   }
0243 #  endif
0244 
0245   return __idx;
0246 }
0247 
0248 template <class _ForwardIterator>
0249 inline _LIBCPP_HIDE_FROM_ABI void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) {
0250   using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
0251   (void)std::__uninitialized_value_construct<_ValueType>(std::move(__first), std::move(__last));
0252 }
0253 
0254 // uninitialized_value_construct_n
0255 
0256 template <class _ValueType, class _ForwardIterator, class _Size>
0257 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
0258   auto __idx = __first;
0259 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0260   try {
0261 #  endif
0262     for (; __n > 0; ++__idx, (void)--__n)
0263       ::new (std::__voidify(*__idx)) _ValueType();
0264 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0265   } catch (...) {
0266     std::__destroy(__first, __idx);
0267     throw;
0268   }
0269 #  endif
0270 
0271   return __idx;
0272 }
0273 
0274 template <class _ForwardIterator, class _Size>
0275 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
0276   using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
0277   return std::__uninitialized_value_construct_n<_ValueType>(std::move(__first), __n);
0278 }
0279 
0280 // uninitialized_move
0281 
0282 template <class _ValueType,
0283           class _InputIterator,
0284           class _Sentinel1,
0285           class _ForwardIterator,
0286           class _EndPredicate,
0287           class _IterMove>
0288 inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move(
0289     _InputIterator __ifirst,
0290     _Sentinel1 __ilast,
0291     _ForwardIterator __ofirst,
0292     _EndPredicate __stop_moving,
0293     _IterMove __iter_move) {
0294   auto __idx = __ofirst;
0295 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0296   try {
0297 #  endif
0298     for (; __ifirst != __ilast && !__stop_moving(__idx); ++__idx, (void)++__ifirst) {
0299       ::new (std::__voidify(*__idx)) _ValueType(__iter_move(__ifirst));
0300     }
0301 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0302   } catch (...) {
0303     std::__destroy(__ofirst, __idx);
0304     throw;
0305   }
0306 #  endif
0307 
0308   return {std::move(__ifirst), std::move(__idx)};
0309 }
0310 
0311 template <class _InputIterator, class _ForwardIterator>
0312 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0313 uninitialized_move(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIterator __ofirst) {
0314   using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
0315   auto __iter_move = [](auto&& __iter) -> decltype(auto) { return std::move(*__iter); };
0316 
0317   auto __result = std::__uninitialized_move<_ValueType>(
0318       std::move(__ifirst), std::move(__ilast), std::move(__ofirst), __always_false(), __iter_move);
0319   return std::move(__result.second);
0320 }
0321 
0322 // uninitialized_move_n
0323 
0324 template <class _ValueType,
0325           class _InputIterator,
0326           class _Size,
0327           class _ForwardIterator,
0328           class _EndPredicate,
0329           class _IterMove>
0330 inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move_n(
0331     _InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _EndPredicate __stop_moving, _IterMove __iter_move) {
0332   auto __idx = __ofirst;
0333 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0334   try {
0335 #  endif
0336     for (; __n > 0 && !__stop_moving(__idx); ++__idx, (void)++__ifirst, --__n)
0337       ::new (std::__voidify(*__idx)) _ValueType(__iter_move(__ifirst));
0338 #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0339   } catch (...) {
0340     std::__destroy(__ofirst, __idx);
0341     throw;
0342   }
0343 #  endif
0344 
0345   return {std::move(__ifirst), std::move(__idx)};
0346 }
0347 
0348 template <class _InputIterator, class _Size, class _ForwardIterator>
0349 inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
0350 uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) {
0351   using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
0352   auto __iter_move = [](auto&& __iter) -> decltype(auto) { return std::move(*__iter); };
0353 
0354   return std::__uninitialized_move_n<_ValueType>(
0355       std::move(__ifirst), __n, std::move(__ofirst), __always_false(), __iter_move);
0356 }
0357 
0358 // TODO: Rewrite this to iterate left to right and use reverse_iterators when calling
0359 // Destroys every element in the range [first, last) FROM RIGHT TO LEFT using allocator
0360 // destruction. If elements are themselves C-style arrays, they are recursively destroyed
0361 // in the same manner.
0362 //
0363 // This function assumes that destructors do not throw, and that the allocator is bound to
0364 // the correct type.
0365 template <class _Alloc,
0366           class _BidirIter,
0367           __enable_if_t<__has_bidirectional_iterator_category<_BidirIter>::value, int> = 0>
0368 _LIBCPP_HIDE_FROM_ABI constexpr void
0369 __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter __first, _BidirIter __last) noexcept {
0370   using _ValueType = typename iterator_traits<_BidirIter>::value_type;
0371   static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _ValueType>,
0372                 "The allocator should already be rebound to the correct type");
0373 
0374   if (__first == __last)
0375     return;
0376 
0377   if constexpr (is_array_v<_ValueType>) {
0378     static_assert(!__libcpp_is_unbounded_array<_ValueType>::value,
0379                   "arrays of unbounded arrays don't exist, but if they did we would mess up here");
0380 
0381     using _Element = remove_extent_t<_ValueType>;
0382     __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc);
0383     do {
0384       --__last;
0385       decltype(auto) __array = *__last;
0386       std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + extent_v<_ValueType>);
0387     } while (__last != __first);
0388   } else {
0389     do {
0390       --__last;
0391       allocator_traits<_Alloc>::destroy(__alloc, std::addressof(*__last));
0392     } while (__last != __first);
0393   }
0394 }
0395 
0396 // Constructs the object at the given location using the allocator's construct method.
0397 //
0398 // If the object being constructed is an array, each element of the array is allocator-constructed,
0399 // recursively. If an exception is thrown during the construction of an array, the initialized
0400 // elements are destroyed in reverse order of initialization using allocator destruction.
0401 //
0402 // This function assumes that the allocator is bound to the correct type.
0403 template <class _Alloc, class _Tp>
0404 _LIBCPP_HIDE_FROM_ABI constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc) {
0405   static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>,
0406                 "The allocator should already be rebound to the correct type");
0407 
0408   if constexpr (is_array_v<_Tp>) {
0409     using _Element = remove_extent_t<_Tp>;
0410     __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc);
0411     size_t __i   = 0;
0412     _Tp& __array = *__loc;
0413 
0414     // If an exception is thrown, destroy what we have constructed so far in reverse order.
0415     auto __guard = std::__make_exception_guard([&]() {
0416       std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i);
0417     });
0418 
0419     for (; __i != extent_v<_Tp>; ++__i) {
0420       std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]));
0421     }
0422     __guard.__complete();
0423   } else {
0424     allocator_traits<_Alloc>::construct(__alloc, __loc);
0425   }
0426 }
0427 
0428 // Constructs the object at the given location using the allocator's construct method, passing along
0429 // the provided argument.
0430 //
0431 // If the object being constructed is an array, the argument is also assumed to be an array. Each
0432 // each element of the array being constructed is allocator-constructed from the corresponding
0433 // element of the argument array. If an exception is thrown during the construction of an array,
0434 // the initialized elements are destroyed in reverse order of initialization using allocator
0435 // destruction.
0436 //
0437 // This function assumes that the allocator is bound to the correct type.
0438 template <class _Alloc, class _Tp, class _Arg>
0439 _LIBCPP_HIDE_FROM_ABI constexpr void
0440 __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) {
0441   static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>,
0442                 "The allocator should already be rebound to the correct type");
0443 
0444   if constexpr (is_array_v<_Tp>) {
0445     static_assert(is_array_v<_Arg>,
0446                   "Provided non-array initialization argument to __allocator_construct_at_multidimensional when "
0447                   "trying to construct an array.");
0448 
0449     using _Element = remove_extent_t<_Tp>;
0450     __allocator_traits_rebind_t<_Alloc, _Element> __elem_alloc(__alloc);
0451     size_t __i   = 0;
0452     _Tp& __array = *__loc;
0453 
0454     // If an exception is thrown, destroy what we have constructed so far in reverse order.
0455     auto __guard = std::__make_exception_guard([&]() {
0456       std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i);
0457     });
0458     for (; __i != extent_v<_Tp>; ++__i) {
0459       std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]), __arg[__i]);
0460     }
0461     __guard.__complete();
0462   } else {
0463     allocator_traits<_Alloc>::construct(__alloc, __loc, __arg);
0464   }
0465 }
0466 
0467 // Given a range starting at it and containing n elements, initializes each element in the
0468 // range from left to right using the construct method of the allocator (rebound to the
0469 // correct type).
0470 //
0471 // If an exception is thrown, the initialized elements are destroyed in reverse order of
0472 // initialization using allocator_traits destruction. If the elements in the range are C-style
0473 // arrays, they are initialized element-wise using allocator construction, and recursively so.
0474 template <class _Alloc,
0475           class _BidirIter,
0476           class _Tp,
0477           class _Size = typename iterator_traits<_BidirIter>::difference_type>
0478 _LIBCPP_HIDE_FROM_ABI constexpr void
0479 __uninitialized_allocator_fill_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) {
0480   using _ValueType = typename iterator_traits<_BidirIter>::value_type;
0481   __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc);
0482   _BidirIter __begin = __it;
0483 
0484   // If an exception is thrown, destroy what we have constructed so far in reverse order.
0485   auto __guard =
0486       std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
0487   for (; __n != 0; --__n, ++__it) {
0488     std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it), __value);
0489   }
0490   __guard.__complete();
0491 }
0492 
0493 // Same as __uninitialized_allocator_fill_n_multidimensional, but doesn't pass any initialization argument
0494 // to the allocator's construct method, which results in value initialization.
0495 template <class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type>
0496 _LIBCPP_HIDE_FROM_ABI constexpr void
0497 __uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n) {
0498   using _ValueType = typename iterator_traits<_BidirIter>::value_type;
0499   __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc);
0500   _BidirIter __begin = __it;
0501 
0502   // If an exception is thrown, destroy what we have constructed so far in reverse order.
0503   auto __guard =
0504       std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
0505   for (; __n != 0; --__n, ++__it) {
0506     std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it));
0507   }
0508   __guard.__complete();
0509 }
0510 
0511 #endif // _LIBCPP_STD_VER >= 17
0512 
0513 // Destroy all elements in [__first, __last) from left to right using allocator destruction.
0514 template <class _Alloc, class _Iter, class _Sent>
0515 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
0516 __allocator_destroy(_Alloc& __alloc, _Iter __first, _Sent __last) {
0517   for (; __first != __last; ++__first)
0518     allocator_traits<_Alloc>::destroy(__alloc, std::__to_address(__first));
0519 }
0520 
0521 template <class _Alloc, class _Iter>
0522 class _AllocatorDestroyRangeReverse {
0523 public:
0524   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
0525   _AllocatorDestroyRangeReverse(_Alloc& __alloc, _Iter& __first, _Iter& __last)
0526       : __alloc_(__alloc), __first_(__first), __last_(__last) {}
0527 
0528   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void operator()() const {
0529     std::__allocator_destroy(__alloc_, std::reverse_iterator<_Iter>(__last_), std::reverse_iterator<_Iter>(__first_));
0530   }
0531 
0532 private:
0533   _Alloc& __alloc_;
0534   _Iter& __first_;
0535   _Iter& __last_;
0536 };
0537 
0538 // Copy-construct [__first1, __last1) in [__first2, __first2 + N), where N is distance(__first1, __last1).
0539 //
0540 // The caller has to ensure that __first2 can hold at least N uninitialized elements. If an exception is thrown the
0541 // already copied elements are destroyed in reverse order of their construction.
0542 template <class _Alloc, class _Iter1, class _Sent1, class _Iter2>
0543 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2
0544 __uninitialized_allocator_copy_impl(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) {
0545   auto __destruct_first = __first2;
0546   auto __guard =
0547       std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2));
0548   while (__first1 != __last1) {
0549     allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), *__first1);
0550     ++__first1;
0551     ++__first2;
0552   }
0553   __guard.__complete();
0554   return __first2;
0555 }
0556 
0557 template <class _Alloc, class _Type>
0558 struct __allocator_has_trivial_copy_construct : _Not<__has_construct<_Alloc, _Type*, const _Type&> > {};
0559 
0560 template <class _Type>
0561 struct __allocator_has_trivial_copy_construct<allocator<_Type>, _Type> : true_type {};
0562 
0563 template <class _Alloc,
0564           class _In,
0565           class _RawTypeIn = __remove_const_t<_In>,
0566           class _Out,
0567           __enable_if_t<
0568               // using _RawTypeIn because of the allocator<T const> extension
0569               is_trivially_copy_constructible<_RawTypeIn>::value && is_trivially_copy_assignable<_RawTypeIn>::value &&
0570                   is_same<__remove_const_t<_In>, __remove_const_t<_Out> >::value &&
0571                   __allocator_has_trivial_copy_construct<_Alloc, _RawTypeIn>::value,
0572               int> = 0>
0573 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Out*
0574 __uninitialized_allocator_copy_impl(_Alloc&, _In* __first1, _In* __last1, _Out* __first2) {
0575   // TODO: Remove the const_cast once we drop support for std::allocator<T const>
0576   if (__libcpp_is_constant_evaluated()) {
0577     while (__first1 != __last1) {
0578       std::__construct_at(std::__to_address(__first2), *__first1);
0579       ++__first1;
0580       ++__first2;
0581     }
0582     return __first2;
0583   } else {
0584     return std::copy(__first1, __last1, const_cast<_RawTypeIn*>(__first2));
0585   }
0586 }
0587 
0588 template <class _Alloc, class _Iter1, class _Sent1, class _Iter2>
0589 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2
0590 __uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) {
0591   auto __unwrapped_range = std::__unwrap_range(__first1, __last1);
0592   auto __result          = std::__uninitialized_allocator_copy_impl(
0593       __alloc, __unwrapped_range.first, __unwrapped_range.second, std::__unwrap_iter(__first2));
0594   return std::__rewrap_iter(__first2, __result);
0595 }
0596 
0597 template <class _Alloc, class _Type>
0598 struct __allocator_has_trivial_move_construct : _Not<__has_construct<_Alloc, _Type*, _Type&&> > {};
0599 
0600 template <class _Type>
0601 struct __allocator_has_trivial_move_construct<allocator<_Type>, _Type> : true_type {};
0602 
0603 template <class _Alloc, class _Tp>
0604 struct __allocator_has_trivial_destroy : _Not<__has_destroy<_Alloc, _Tp*> > {};
0605 
0606 template <class _Tp, class _Up>
0607 struct __allocator_has_trivial_destroy<allocator<_Tp>, _Up> : true_type {};
0608 
0609 // __uninitialized_allocator_relocate relocates the objects in [__first, __last) into __result.
0610 // Relocation means that the objects in [__first, __last) are placed into __result as-if by move-construct and destroy,
0611 // except that the move constructor and destructor may never be called if they are known to be equivalent to a memcpy.
0612 //
0613 // Preconditions:  __result doesn't contain any objects and [__first, __last) contains objects
0614 // Postconditions: __result contains the objects from [__first, __last) and
0615 //                 [__first, __last) doesn't contain any objects
0616 //
0617 // The strong exception guarantee is provided if any of the following are true:
0618 // - is_nothrow_move_constructible<_Tp>
0619 // - is_copy_constructible<_Tp>
0620 // - __libcpp_is_trivially_relocatable<_Tp>
0621 template <class _Alloc, class _Tp>
0622 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
0623 __uninitialized_allocator_relocate(_Alloc& __alloc, _Tp* __first, _Tp* __last, _Tp* __result) {
0624   static_assert(__is_cpp17_move_insertable<_Alloc>::value,
0625                 "The specified type does not meet the requirements of Cpp17MoveInsertable");
0626   if (__libcpp_is_constant_evaluated() || !__libcpp_is_trivially_relocatable<_Tp>::value ||
0627       !__allocator_has_trivial_move_construct<_Alloc, _Tp>::value ||
0628       !__allocator_has_trivial_destroy<_Alloc, _Tp>::value) {
0629     auto __destruct_first = __result;
0630     auto __guard =
0631         std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Tp*>(__alloc, __destruct_first, __result));
0632     auto __iter = __first;
0633     while (__iter != __last) {
0634 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0635       allocator_traits<_Alloc>::construct(__alloc, __result, std::move_if_noexcept(*__iter));
0636 #else
0637       allocator_traits<_Alloc>::construct(__alloc, __result, std::move(*__iter));
0638 #endif
0639       ++__iter;
0640       ++__result;
0641     }
0642     __guard.__complete();
0643     std::__allocator_destroy(__alloc, __first, __last);
0644   } else {
0645     // Casting to void* to suppress clang complaining that this is technically UB.
0646     __builtin_memcpy(static_cast<void*>(__result), __first, sizeof(_Tp) * (__last - __first));
0647   }
0648 }
0649 
0650 _LIBCPP_END_NAMESPACE_STD
0651 
0652 _LIBCPP_POP_MACROS
0653 
0654 #endif // _LIBCPP___CXX03___MEMORY_UNINITIALIZED_ALGORITHMS_H