1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H
11#define _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H
12
13#include <__algorithm/copy.h>
14#include <__algorithm/in_out_result.h>
15#include <__algorithm/unwrap_iter.h>
16#include <__algorithm/unwrap_range.h>
17#include <__config>
18#include <__fwd/memory.h>
19#include <__iterator/iterator_traits.h>
20#include <__iterator/reverse_iterator.h>
21#include <__memory/addressof.h>
22#include <__memory/allocator_traits.h>
23#include <__memory/construct_at.h>
24#include <__memory/destroy.h>
25#include <__memory/pointer_traits.h>
26#include <__type_traits/enable_if.h>
27#include <__type_traits/is_constant_evaluated.h>
28#include <__type_traits/is_reference.h>
29#include <__type_traits/is_same.h>
30#include <__type_traits/is_trivially_assignable.h>
31#include <__type_traits/is_trivially_constructible.h>
32#include <__type_traits/is_trivially_relocatable.h>
33#include <__type_traits/remove_const.h>
34#include <__utility/exception_guard.h>
35#include <__utility/move.h>
36#include <__utility/pair.h>
37
38#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
39# pragma GCC system_header
40#endif
41
42_LIBCPP_PUSH_MACROS
43#include <__undef_macros>
44
45_LIBCPP_BEGIN_NAMESPACE_STD
46
47struct __always_false {
48 template <class... _Args>
49 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator()(_Args&&...) const _NOEXCEPT {
50 return false;
51 }
52};
53
54// uninitialized_copy
55
56template <class _ValueType, class _InputIterator, class _Sentinel1, class _ForwardIterator, class _EndPredicate>
57inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __in_out_result<_InputIterator, _ForwardIterator>
58__uninitialized_copy(
59 _InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _EndPredicate __stop_copying) {
60 _ForwardIterator __idx = __ofirst;
61 auto __guard = std::__make_exception_guard([&] { std::__destroy(__ofirst, __idx); });
62 for (; __ifirst != __ilast && !__stop_copying(__idx); ++__ifirst, (void)++__idx)
63 ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(*__ifirst);
64 __guard.__complete();
65
66 return {std::move(__ifirst), std::move(__idx)};
67}
68
69template <class _InputIterator, class _ForwardIterator>
70_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
71uninitialized_copy(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIterator __ofirst) {
72 typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
73 auto __result = std::__uninitialized_copy<_ValueType>(
74 std::move(__ifirst), std::move(__ilast), std::move(__ofirst), __always_false());
75 return std::move(__result.__out_);
76}
77
78// uninitialized_copy_n
79
80template <class _ValueType, class _InputIterator, class _Size, class _ForwardIterator, class _EndPredicate>
81inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __in_out_result<_InputIterator, _ForwardIterator>
82__uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _EndPredicate __stop_copying) {
83 _ForwardIterator __idx = __ofirst;
84 auto __guard = std::__make_exception_guard([&] { std::__destroy(__ofirst, __idx); });
85 for (; __n > 0 && !__stop_copying(__idx); ++__ifirst, (void)++__idx, (void)--__n)
86 ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(*__ifirst);
87 __guard.__complete();
88
89 return {std::move(__ifirst), std::move(__idx)};
90}
91
92template <class _InputIterator, class _Size, class _ForwardIterator>
93inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
94uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) {
95 typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
96 auto __result =
97 std::__uninitialized_copy_n<_ValueType>(std::move(__ifirst), __n, std::move(__ofirst), __always_false());
98 return std::move(__result.__out_);
99}
100
101// uninitialized_fill
102
103template <class _ValueType, class _ForwardIterator, class _Sentinel, class _Tp>
104inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
105__uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) {
106 _ForwardIterator __idx = __first;
107 auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
108 for (; __idx != __last; ++__idx)
109 ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__x);
110 __guard.__complete();
111
112 return __idx;
113}
114
115template <class _ForwardIterator, class _Tp>
116inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
117uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __x) {
118 typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
119 (void)std::__uninitialized_fill<_ValueType>(__first, __last, __x);
120}
121
122// uninitialized_fill_n
123
124template <class _ValueType, class _ForwardIterator, class _Size, class _Tp>
125inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
126__uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
127 _ForwardIterator __idx = __first;
128 auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
129 for (; __n > 0; ++__idx, (void)--__n)
130 ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__x);
131 __guard.__complete();
132
133 return __idx;
134}
135
136template <class _ForwardIterator, class _Size, class _Tp>
137inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
138uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
139 typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
140 return std::__uninitialized_fill_n<_ValueType>(__first, __n, __x);
141}
142
143#if _LIBCPP_STD_VER >= 17
144
145template <class _Iter>
146_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) __deref_move(_Iter& __it) {
147 if constexpr (is_lvalue_reference_v<decltype(*__it)>)
148 return std::move(*__it);
149 else
150 return *__it;
151}
152
153// uninitialized_default_construct
154
155template <class _ValueType, class _ForwardIterator, class _Sentinel>
156inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
157__uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) {
158 auto __idx = __first;
159 auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
160 for (; __idx != __last; ++__idx)
161 ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType;
162 __guard.__complete();
163
164 return __idx;
165}
166
167template <class _ForwardIterator>
168inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
169uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) {
170 using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
171 (void)std::__uninitialized_default_construct<_ValueType>(std::move(__first), std::move(__last));
172}
173
174// uninitialized_default_construct_n
175
176template <class _ValueType, class _ForwardIterator, class _Size>
177inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
178__uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
179 auto __idx = __first;
180 auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
181 for (; __n > 0; ++__idx, (void)--__n)
182 ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType;
183 __guard.__complete();
184
185 return __idx;
186}
187
188template <class _ForwardIterator, class _Size>
189inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
190uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
191 using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
192 return std::__uninitialized_default_construct_n<_ValueType>(std::move(__first), __n);
193}
194
195// uninitialized_value_construct
196
197template <class _ValueType, class _ForwardIterator, class _Sentinel>
198inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
199__uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) {
200 auto __idx = __first;
201 auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
202 for (; __idx != __last; ++__idx)
203 ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType();
204 __guard.__complete();
205
206 return __idx;
207}
208
209template <class _ForwardIterator>
210inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
211uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) {
212 using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
213 (void)std::__uninitialized_value_construct<_ValueType>(std::move(__first), std::move(__last));
214}
215
216// uninitialized_value_construct_n
217
218template <class _ValueType, class _ForwardIterator, class _Size>
219inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
220__uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
221 auto __idx = __first;
222 auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
223 for (; __n > 0; ++__idx, (void)--__n)
224 ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType();
225 __guard.__complete();
226
227 return __idx;
228}
229
230template <class _ForwardIterator, class _Size>
231inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
232uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
233 using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
234 return std::__uninitialized_value_construct_n<_ValueType>(std::move(__first), __n);
235}
236
237// uninitialized_move
238
239template <class _ValueType,
240 class _InputIterator,
241 class _Sentinel1,
242 class _ForwardIterator,
243 class _EndPredicate,
244 class _IterMove>
245inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __in_out_result<_InputIterator, _ForwardIterator>
246__uninitialized_move(_InputIterator __ifirst,
247 _Sentinel1 __ilast,
248 _ForwardIterator __ofirst,
249 _EndPredicate __stop_moving,
250 _IterMove __iter_move) {
251 auto __idx = __ofirst;
252 auto __guard = std::__make_exception_guard([&] { std::__destroy(__ofirst, __idx); });
253 for (; __ifirst != __ilast && !__stop_moving(__idx); ++__idx, (void)++__ifirst) {
254 ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__iter_move(__ifirst));
255 }
256 __guard.__complete();
257
258 return {std::move(__ifirst), std::move(__idx)};
259}
260
261template <class _InputIterator, class _ForwardIterator>
262inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
263uninitialized_move(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIterator __ofirst) {
264 using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
265 auto __iter_move = [](auto&& __iter) -> decltype(auto) { return std::__deref_move(__iter); };
266
267 auto __result = std::__uninitialized_move<_ValueType>(
268 std::move(__ifirst), std::move(__ilast), std::move(__ofirst), __always_false(), __iter_move);
269 return std::move(__result.__out_);
270}
271
272// uninitialized_move_n
273
274template <class _ValueType,
275 class _InputIterator,
276 class _Size,
277 class _ForwardIterator,
278 class _EndPredicate,
279 class _IterMove>
280inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __in_out_result<_InputIterator, _ForwardIterator>
281__uninitialized_move_n(
282 _InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _EndPredicate __stop_moving, _IterMove __iter_move) {
283 auto __idx = __ofirst;
284 auto __guard = std::__make_exception_guard([&] { std::__destroy(__ofirst, __idx); });
285 for (; __n > 0 && !__stop_moving(__idx); ++__idx, (void)++__ifirst, --__n)
286 ::new (static_cast<void*>(std::addressof(*__idx))) _ValueType(__iter_move(__ifirst));
287 __guard.__complete();
288
289 return {std::move(__ifirst), std::move(__idx)};
290}
291
292template <class _InputIterator, class _Size, class _ForwardIterator>
293inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<_InputIterator, _ForwardIterator>
294uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) {
295 using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
296 auto __iter_move = [](auto&& __iter) -> decltype(auto) { return std::__deref_move(__iter); };
297
298 auto __result = std::__uninitialized_move_n<_ValueType>(
299 std::move(__ifirst), __n, std::move(__ofirst), __always_false(), __iter_move);
300 return {std::move(__result.__in_), std::move(__result.__out_)};
301}
302
303#endif // _LIBCPP_STD_VER >= 17
304
305template <class _Alloc, class _Iter>
306class _AllocatorDestroyRangeReverse {
307public:
308 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
309 _AllocatorDestroyRangeReverse(_Alloc& __alloc, _Iter& __first, _Iter& __last)
310 : __alloc_(__alloc), __first_(__first), __last_(__last) {}
311
312 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void operator()() const {
313 std::__allocator_destroy(__alloc_, std::reverse_iterator<_Iter>(__last_), std::reverse_iterator<_Iter>(__first_));
314 }
315
316private:
317 _Alloc& __alloc_;
318 _Iter& __first_;
319 _Iter& __last_;
320};
321
322// Copy-construct [__first1, __last1) in [__first2, __first2 + N), where N is distance(__first1, __last1).
323//
324// The caller has to ensure that __first2 can hold at least N uninitialized elements. If an exception is thrown the
325// already copied elements are destroyed in reverse order of their construction.
326template <class _Alloc, class _Iter1, class _Sent1, class _Iter2>
327_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2
328__uninitialized_allocator_copy_impl(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) {
329 auto __destruct_first = __first2;
330 auto __guard =
331 std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2));
332 while (__first1 != __last1) {
333 allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), *__first1);
334 ++__first1;
335 ++__first2;
336 }
337 __guard.__complete();
338 return __first2;
339}
340
341template <class _Alloc, class _Type>
342inline const bool __allocator_has_trivial_copy_construct_v = !__has_construct_v<_Alloc, _Type*, const _Type&>;
343
344template <class _Type>
345inline const bool __allocator_has_trivial_copy_construct_v<allocator<_Type>, _Type> = true;
346
347template <class _Alloc,
348 class _In,
349 class _Out,
350 __enable_if_t<is_trivially_copy_constructible<_In>::value && is_trivially_assignable<_Out&, _In&>::value &&
351 is_same<__remove_const_t<_In>, __remove_const_t<_Out> >::value &&
352 __allocator_has_trivial_copy_construct_v<_Alloc, _In>,
353 int> = 0>
354_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Out*
355__uninitialized_allocator_copy_impl(_Alloc&, _In* __first1, _In* __last1, _Out* __first2) {
356 if (__libcpp_is_constant_evaluated()) {
357 while (__first1 != __last1) {
358 std::__construct_at(std::__to_address(__first2), *__first1);
359 ++__first1;
360 ++__first2;
361 }
362 return __first2;
363 } else {
364 return std::copy(__first1, __last1, __first2);
365 }
366}
367
368template <class _Alloc, class _Iter1, class _Sent1, class _Iter2>
369_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2
370__uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) {
371 auto __unwrapped_range = std::__unwrap_range(std::move(__first1), std::move(__last1));
372 auto __result = std::__uninitialized_allocator_copy_impl(
373 __alloc, std::move(__unwrapped_range.first), std::move(__unwrapped_range.second), std::__unwrap_iter(__first2));
374 return std::__rewrap_iter(__first2, __result);
375}
376
377template <class _Alloc, class _Type>
378inline const bool __allocator_has_trivial_move_construct_v = !__has_construct_v<_Alloc, _Type*, _Type&&>;
379
380template <class _Type>
381inline const bool __allocator_has_trivial_move_construct_v<allocator<_Type>, _Type> = true;
382
383template <class _Alloc, class _Tp>
384inline const bool __allocator_has_trivial_destroy_v = !__has_destroy_v<_Alloc, _Tp*>;
385
386template <class _Tp, class _Up>
387inline const bool __allocator_has_trivial_destroy_v<allocator<_Tp>, _Up> = true;
388
389// __uninitialized_allocator_relocate relocates the objects in [__first, __last) into __result.
390// Relocation means that the objects in [__first, __last) are placed into __result as-if by move-construct and destroy,
391// except that the move constructor and destructor may never be called if they are known to be equivalent to a memcpy.
392//
393// Preconditions: __result doesn't contain any objects and [__first, __last) contains objects
394// Postconditions: __result contains the objects from [__first, __last) and
395// [__first, __last) doesn't contain any objects
396//
397// The strong exception guarantee is provided if any of the following are true:
398// - is_nothrow_move_constructible<_ValueType>
399// - is_copy_constructible<_ValueType>
400// - __libcpp_is_trivially_relocatable<_ValueType>
401template <class _Alloc, class _ContiguousIterator>
402_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __uninitialized_allocator_relocate(
403 _Alloc& __alloc, _ContiguousIterator __first, _ContiguousIterator __last, _ContiguousIterator __result) {
404 static_assert(__libcpp_is_contiguous_iterator<_ContiguousIterator>::value, "");
405 using _ValueType = typename iterator_traits<_ContiguousIterator>::value_type;
406 static_assert(
407 __is_cpp17_move_insertable_v<_Alloc>, "The specified type does not meet the requirements of Cpp17MoveInsertable");
408 if (__libcpp_is_constant_evaluated() || !__libcpp_is_trivially_relocatable<_ValueType>::value ||
409 !__allocator_has_trivial_move_construct_v<_Alloc, _ValueType> ||
410 !__allocator_has_trivial_destroy_v<_Alloc, _ValueType>) {
411 auto __destruct_first = __result;
412 auto __guard = std::__make_exception_guard(
413 _AllocatorDestroyRangeReverse<_Alloc, _ContiguousIterator>(__alloc, __destruct_first, __result));
414 auto __iter = __first;
415 while (__iter != __last) {
416#if _LIBCPP_HAS_EXCEPTIONS
417 allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__result), std::move_if_noexcept(*__iter));
418#else
419 allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__result), std::move(*__iter));
420#endif
421 ++__iter;
422 ++__result;
423 }
424 __guard.__complete();
425 std::__allocator_destroy(__alloc, __first, __last);
426 } else {
427 // Casting to void* to suppress clang complaining that this is technically UB.
428 __builtin_memcpy(static_cast<void*>(std::__to_address(__result)),
429 std::__to_address(__first),
430 sizeof(_ValueType) * (__last - __first));
431 }
432}
433
434_LIBCPP_END_NAMESPACE_STD
435
436_LIBCPP_POP_MACROS
437
438#endif // _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H
439