1 | // Raw memory manipulators -*- C++ -*- |
2 | |
3 | // Copyright (C) 2001-2024 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /* |
26 | * |
27 | * Copyright (c) 1994 |
28 | * Hewlett-Packard Company |
29 | * |
30 | * Permission to use, copy, modify, distribute and sell this software |
31 | * and its documentation for any purpose is hereby granted without fee, |
32 | * provided that the above copyright notice appear in all copies and |
33 | * that both that copyright notice and this permission notice appear |
34 | * in supporting documentation. Hewlett-Packard Company makes no |
35 | * representations about the suitability of this software for any |
36 | * purpose. It is provided "as is" without express or implied warranty. |
37 | * |
38 | * |
39 | * Copyright (c) 1996,1997 |
40 | * Silicon Graphics Computer Systems, Inc. |
41 | * |
42 | * Permission to use, copy, modify, distribute and sell this software |
43 | * and its documentation for any purpose is hereby granted without fee, |
44 | * provided that the above copyright notice appear in all copies and |
45 | * that both that copyright notice and this permission notice appear |
46 | * in supporting documentation. Silicon Graphics makes no |
47 | * representations about the suitability of this software for any |
48 | * purpose. It is provided "as is" without express or implied warranty. |
49 | */ |
50 | |
51 | /** @file bits/stl_uninitialized.h |
52 | * This is an internal header file, included by other library headers. |
53 | * Do not attempt to use it directly. @headername{memory} |
54 | */ |
55 | |
56 | #ifndef _STL_UNINITIALIZED_H |
57 | #define _STL_UNINITIALIZED_H 1 |
58 | |
59 | #if __cplusplus >= 201103L |
60 | #include <type_traits> |
61 | #endif |
62 | |
63 | #include <bits/stl_algobase.h> // copy |
64 | #include <ext/alloc_traits.h> // __alloc_traits |
65 | |
66 | #if __cplusplus >= 201703L |
67 | #include <bits/stl_pair.h> |
68 | #endif |
69 | |
70 | namespace std _GLIBCXX_VISIBILITY(default) |
71 | { |
72 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
73 | |
74 | /** @addtogroup memory |
75 | * @{ |
76 | */ |
77 | |
78 | /// @cond undocumented |
79 | |
80 | #if __cplusplus >= 201103L |
81 | template<typename _ValueType, typename _Tp> |
82 | constexpr bool |
83 | __check_constructible() |
84 | { |
85 | // Trivial types can have deleted constructors, but std::copy etc. |
86 | // only use assignment (or memmove) not construction, so we need an |
87 | // explicit check that construction from _Tp is actually valid, |
88 | // otherwise some ill-formed uses of std::uninitialized_xxx would |
89 | // compile without errors. This gives a nice clear error message. |
90 | static_assert(is_constructible<_ValueType, _Tp>::value, |
91 | "result type must be constructible from input type" ); |
92 | |
93 | return true; |
94 | } |
95 | |
96 | // If the type is trivial we don't need to construct it, just assign to it. |
97 | // But trivial types can still have deleted or inaccessible assignment, |
98 | // so don't try to use std::copy or std::fill etc. if we can't assign. |
99 | # define _GLIBCXX_USE_ASSIGN_FOR_INIT(T, U) \ |
100 | __is_trivial(T) && __is_assignable(T&, U) \ |
101 | && std::__check_constructible<T, U>() |
102 | #else |
103 | // No need to check if is_constructible<T, U> for C++98. Trivial types have |
104 | // no user-declared constructors, so if the assignment is valid, construction |
105 | // should be too. |
106 | # define _GLIBCXX_USE_ASSIGN_FOR_INIT(T, U) \ |
107 | __is_trivial(T) && __is_assignable(T&, U) |
108 | #endif |
109 | |
110 | template<typename _InputIterator, typename _ForwardIterator> |
111 | _GLIBCXX20_CONSTEXPR |
112 | _ForwardIterator |
113 | __do_uninit_copy(_InputIterator __first, _InputIterator __last, |
114 | _ForwardIterator __result) |
115 | { |
116 | _ForwardIterator __cur = __result; |
117 | __try |
118 | { |
119 | for (; __first != __last; ++__first, (void)++__cur) |
120 | std::_Construct(std::__addressof(*__cur), *__first); |
121 | return __cur; |
122 | } |
123 | __catch(...) |
124 | { |
125 | std::_Destroy(__result, __cur); |
126 | __throw_exception_again; |
127 | } |
128 | } |
129 | |
130 | template<bool _TrivialValueTypes> |
131 | struct __uninitialized_copy |
132 | { |
133 | template<typename _InputIterator, typename _ForwardIterator> |
134 | static _ForwardIterator |
135 | __uninit_copy(_InputIterator __first, _InputIterator __last, |
136 | _ForwardIterator __result) |
137 | { return std::__do_uninit_copy(__first, __last, __result); } |
138 | }; |
139 | |
140 | template<> |
141 | struct __uninitialized_copy<true> |
142 | { |
143 | template<typename _InputIterator, typename _ForwardIterator> |
144 | static _ForwardIterator |
145 | __uninit_copy(_InputIterator __first, _InputIterator __last, |
146 | _ForwardIterator __result) |
147 | { return std::copy(__first, __last, __result); } |
148 | }; |
149 | |
150 | /// @endcond |
151 | |
152 | /** |
153 | * @brief Copies the range [first,last) into result. |
154 | * @param __first An input iterator. |
155 | * @param __last An input iterator. |
156 | * @param __result An output iterator. |
157 | * @return __result + (__first - __last) |
158 | * |
159 | * Like copy(), but does not require an initialized output range. |
160 | */ |
161 | template<typename _InputIterator, typename _ForwardIterator> |
162 | inline _ForwardIterator |
163 | uninitialized_copy(_InputIterator __first, _InputIterator __last, |
164 | _ForwardIterator __result) |
165 | { |
166 | typedef typename iterator_traits<_InputIterator>::value_type |
167 | _ValueType1; |
168 | typedef typename iterator_traits<_ForwardIterator>::value_type |
169 | _ValueType2; |
170 | |
171 | // _ValueType1 must be trivially-copyable to use memmove, so don't |
172 | // bother optimizing to std::copy if it isn't. |
173 | // XXX Unnecessary because std::copy would check it anyway? |
174 | const bool __can_memmove = __is_trivial(_ValueType1); |
175 | |
176 | #if __cplusplus < 201103L |
177 | typedef typename iterator_traits<_InputIterator>::reference _From; |
178 | #else |
179 | using _From = decltype(*__first); |
180 | #endif |
181 | const bool __assignable |
182 | = _GLIBCXX_USE_ASSIGN_FOR_INIT(_ValueType2, _From); |
183 | |
184 | return std::__uninitialized_copy<__can_memmove && __assignable>:: |
185 | __uninit_copy(__first, __last, __result); |
186 | } |
187 | |
188 | /// @cond undocumented |
189 | |
190 | template<typename _ForwardIterator, typename _Tp> |
191 | _GLIBCXX20_CONSTEXPR void |
192 | __do_uninit_fill(_ForwardIterator __first, _ForwardIterator __last, |
193 | const _Tp& __x) |
194 | { |
195 | _ForwardIterator __cur = __first; |
196 | __try |
197 | { |
198 | for (; __cur != __last; ++__cur) |
199 | std::_Construct(std::__addressof(*__cur), __x); |
200 | } |
201 | __catch(...) |
202 | { |
203 | std::_Destroy(__first, __cur); |
204 | __throw_exception_again; |
205 | } |
206 | } |
207 | |
208 | template<bool _TrivialValueType> |
209 | struct __uninitialized_fill |
210 | { |
211 | template<typename _ForwardIterator, typename _Tp> |
212 | static void |
213 | __uninit_fill(_ForwardIterator __first, _ForwardIterator __last, |
214 | const _Tp& __x) |
215 | { std::__do_uninit_fill(__first, __last, __x); } |
216 | }; |
217 | |
218 | template<> |
219 | struct __uninitialized_fill<true> |
220 | { |
221 | template<typename _ForwardIterator, typename _Tp> |
222 | static void |
223 | __uninit_fill(_ForwardIterator __first, _ForwardIterator __last, |
224 | const _Tp& __x) |
225 | { std::fill(__first, __last, __x); } |
226 | }; |
227 | |
228 | /// @endcond |
229 | |
230 | /** |
231 | * @brief Copies the value x into the range [first,last). |
232 | * @param __first An input iterator. |
233 | * @param __last An input iterator. |
234 | * @param __x The source value. |
235 | * @return Nothing. |
236 | * |
237 | * Like fill(), but does not require an initialized output range. |
238 | */ |
239 | template<typename _ForwardIterator, typename _Tp> |
240 | inline void |
241 | uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, |
242 | const _Tp& __x) |
243 | { |
244 | typedef typename iterator_traits<_ForwardIterator>::value_type |
245 | _ValueType; |
246 | |
247 | // Trivial types do not need a constructor to begin their lifetime, |
248 | // so try to use std::fill to benefit from its memset optimization. |
249 | const bool __can_fill |
250 | = _GLIBCXX_USE_ASSIGN_FOR_INIT(_ValueType, const _Tp&); |
251 | |
252 | std::__uninitialized_fill<__can_fill>:: |
253 | __uninit_fill(__first, __last, __x); |
254 | } |
255 | |
256 | /// @cond undocumented |
257 | |
258 | template<typename _ForwardIterator, typename _Size, typename _Tp> |
259 | _GLIBCXX20_CONSTEXPR |
260 | _ForwardIterator |
261 | __do_uninit_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) |
262 | { |
263 | _ForwardIterator __cur = __first; |
264 | __try |
265 | { |
266 | for (; __n > 0; --__n, (void) ++__cur) |
267 | std::_Construct(std::__addressof(*__cur), __x); |
268 | return __cur; |
269 | } |
270 | __catch(...) |
271 | { |
272 | std::_Destroy(__first, __cur); |
273 | __throw_exception_again; |
274 | } |
275 | } |
276 | |
277 | template<bool _TrivialValueType> |
278 | struct __uninitialized_fill_n |
279 | { |
280 | template<typename _ForwardIterator, typename _Size, typename _Tp> |
281 | static _ForwardIterator |
282 | __uninit_fill_n(_ForwardIterator __first, _Size __n, |
283 | const _Tp& __x) |
284 | { return std::__do_uninit_fill_n(__first, __n, __x); } |
285 | }; |
286 | |
287 | template<> |
288 | struct __uninitialized_fill_n<true> |
289 | { |
290 | template<typename _ForwardIterator, typename _Size, typename _Tp> |
291 | static _ForwardIterator |
292 | __uninit_fill_n(_ForwardIterator __first, _Size __n, |
293 | const _Tp& __x) |
294 | { return std::fill_n(__first, __n, __x); } |
295 | }; |
296 | |
297 | /// @endcond |
298 | |
299 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
300 | // DR 1339. uninitialized_fill_n should return the end of its range |
301 | /** |
302 | * @brief Copies the value x into the range [first,first+n). |
303 | * @param __first An input iterator. |
304 | * @param __n The number of copies to make. |
305 | * @param __x The source value. |
306 | * @return Nothing. |
307 | * |
308 | * Like fill_n(), but does not require an initialized output range. |
309 | */ |
310 | template<typename _ForwardIterator, typename _Size, typename _Tp> |
311 | inline _ForwardIterator |
312 | uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) |
313 | { |
314 | typedef typename iterator_traits<_ForwardIterator>::value_type |
315 | _ValueType; |
316 | |
317 | // Trivial types do not need a constructor to begin their lifetime, |
318 | // so try to use std::fill_n to benefit from its optimizations. |
319 | const bool __can_fill |
320 | = _GLIBCXX_USE_ASSIGN_FOR_INIT(_ValueType, const _Tp&) |
321 | // For arbitrary class types and floating point types we can't assume |
322 | // that __n > 0 and std::__size_to_integer(__n) > 0 are equivalent, |
323 | // so only use std::fill_n when _Size is already an integral type. |
324 | && __is_integer<_Size>::__value; |
325 | |
326 | return __uninitialized_fill_n<__can_fill>:: |
327 | __uninit_fill_n(__first, __n, __x); |
328 | } |
329 | |
330 | #undef _GLIBCXX_USE_ASSIGN_FOR_INIT |
331 | |
332 | /// @cond undocumented |
333 | |
334 | // Extensions: versions of uninitialized_copy, uninitialized_fill, |
335 | // and uninitialized_fill_n that take an allocator parameter. |
336 | // We dispatch back to the standard versions when we're given the |
337 | // default allocator. For nondefault allocators we do not use |
338 | // any of the POD optimizations. |
339 | |
340 | template<typename _InputIterator, typename _ForwardIterator, |
341 | typename _Allocator> |
342 | _GLIBCXX20_CONSTEXPR |
343 | _ForwardIterator |
344 | __uninitialized_copy_a(_InputIterator __first, _InputIterator __last, |
345 | _ForwardIterator __result, _Allocator& __alloc) |
346 | { |
347 | _ForwardIterator __cur = __result; |
348 | __try |
349 | { |
350 | typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; |
351 | for (; __first != __last; ++__first, (void)++__cur) |
352 | __traits::construct(__alloc, std::__addressof(*__cur), *__first); |
353 | return __cur; |
354 | } |
355 | __catch(...) |
356 | { |
357 | std::_Destroy(__result, __cur, __alloc); |
358 | __throw_exception_again; |
359 | } |
360 | } |
361 | |
362 | #if _GLIBCXX_HOSTED |
363 | template<typename _InputIterator, typename _ForwardIterator, typename _Tp> |
364 | _GLIBCXX20_CONSTEXPR |
365 | inline _ForwardIterator |
366 | __uninitialized_copy_a(_InputIterator __first, _InputIterator __last, |
367 | _ForwardIterator __result, allocator<_Tp>&) |
368 | { |
369 | #ifdef __cpp_lib_is_constant_evaluated |
370 | if (std::is_constant_evaluated()) |
371 | return std::__do_uninit_copy(__first, __last, __result); |
372 | #endif |
373 | return std::uninitialized_copy(__first, __last, __result); |
374 | } |
375 | #endif |
376 | |
377 | template<typename _InputIterator, typename _ForwardIterator, |
378 | typename _Allocator> |
379 | _GLIBCXX20_CONSTEXPR |
380 | inline _ForwardIterator |
381 | __uninitialized_move_a(_InputIterator __first, _InputIterator __last, |
382 | _ForwardIterator __result, _Allocator& __alloc) |
383 | { |
384 | return std::__uninitialized_copy_a(_GLIBCXX_MAKE_MOVE_ITERATOR(__first), |
385 | _GLIBCXX_MAKE_MOVE_ITERATOR(__last), |
386 | __result, __alloc); |
387 | } |
388 | |
389 | template<typename _InputIterator, typename _ForwardIterator, |
390 | typename _Allocator> |
391 | _GLIBCXX20_CONSTEXPR |
392 | inline _ForwardIterator |
393 | __uninitialized_move_if_noexcept_a(_InputIterator __first, |
394 | _InputIterator __last, |
395 | _ForwardIterator __result, |
396 | _Allocator& __alloc) |
397 | { |
398 | return std::__uninitialized_copy_a |
399 | (_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first), |
400 | _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc); |
401 | } |
402 | |
403 | template<typename _ForwardIterator, typename _Tp, typename _Allocator> |
404 | _GLIBCXX20_CONSTEXPR |
405 | void |
406 | __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, |
407 | const _Tp& __x, _Allocator& __alloc) |
408 | { |
409 | _ForwardIterator __cur = __first; |
410 | __try |
411 | { |
412 | typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; |
413 | for (; __cur != __last; ++__cur) |
414 | __traits::construct(__alloc, std::__addressof(*__cur), __x); |
415 | } |
416 | __catch(...) |
417 | { |
418 | std::_Destroy(__first, __cur, __alloc); |
419 | __throw_exception_again; |
420 | } |
421 | } |
422 | |
423 | #if _GLIBCXX_HOSTED |
424 | template<typename _ForwardIterator, typename _Tp, typename _Tp2> |
425 | _GLIBCXX20_CONSTEXPR |
426 | inline void |
427 | __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, |
428 | const _Tp& __x, allocator<_Tp2>&) |
429 | { |
430 | #ifdef __cpp_lib_is_constant_evaluated |
431 | if (std::is_constant_evaluated()) |
432 | return std::__do_uninit_fill(__first, __last, __x); |
433 | #endif |
434 | std::uninitialized_fill(__first, __last, __x); |
435 | } |
436 | #endif |
437 | |
438 | template<typename _ForwardIterator, typename _Size, typename _Tp, |
439 | typename _Allocator> |
440 | _GLIBCXX20_CONSTEXPR |
441 | _ForwardIterator |
442 | __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, |
443 | const _Tp& __x, _Allocator& __alloc) |
444 | { |
445 | _ForwardIterator __cur = __first; |
446 | __try |
447 | { |
448 | typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; |
449 | for (; __n > 0; --__n, (void) ++__cur) |
450 | __traits::construct(__alloc, std::__addressof(*__cur), __x); |
451 | return __cur; |
452 | } |
453 | __catch(...) |
454 | { |
455 | std::_Destroy(__first, __cur, __alloc); |
456 | __throw_exception_again; |
457 | } |
458 | } |
459 | |
460 | #if _GLIBCXX_HOSTED |
461 | template<typename _ForwardIterator, typename _Size, typename _Tp, |
462 | typename _Tp2> |
463 | _GLIBCXX20_CONSTEXPR |
464 | inline _ForwardIterator |
465 | __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, |
466 | const _Tp& __x, allocator<_Tp2>&) |
467 | { |
468 | #ifdef __cpp_lib_is_constant_evaluated |
469 | if (std::is_constant_evaluated()) |
470 | return std::__do_uninit_fill_n(__first, __n, __x); |
471 | #endif |
472 | return std::uninitialized_fill_n(__first, __n, __x); |
473 | } |
474 | #endif |
475 | |
476 | // Extensions: __uninitialized_copy_move, __uninitialized_move_copy, |
477 | // __uninitialized_fill_move, __uninitialized_move_fill. |
478 | // All of these algorithms take a user-supplied allocator, which is used |
479 | // for construction and destruction. |
480 | |
481 | // __uninitialized_copy_move |
482 | // Copies [first1, last1) into [result, result + (last1 - first1)), and |
483 | // move [first2, last2) into |
484 | // [result, result + (last1 - first1) + (last2 - first2)). |
485 | template<typename _InputIterator1, typename _InputIterator2, |
486 | typename _ForwardIterator, typename _Allocator> |
487 | inline _ForwardIterator |
488 | __uninitialized_copy_move(_InputIterator1 __first1, |
489 | _InputIterator1 __last1, |
490 | _InputIterator2 __first2, |
491 | _InputIterator2 __last2, |
492 | _ForwardIterator __result, |
493 | _Allocator& __alloc) |
494 | { |
495 | _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1, |
496 | __result, |
497 | __alloc); |
498 | __try |
499 | { |
500 | return std::__uninitialized_move_a(__first2, __last2, __mid, __alloc); |
501 | } |
502 | __catch(...) |
503 | { |
504 | std::_Destroy(__result, __mid, __alloc); |
505 | __throw_exception_again; |
506 | } |
507 | } |
508 | |
509 | // __uninitialized_move_copy |
510 | // Moves [first1, last1) into [result, result + (last1 - first1)), and |
511 | // copies [first2, last2) into |
512 | // [result, result + (last1 - first1) + (last2 - first2)). |
513 | template<typename _InputIterator1, typename _InputIterator2, |
514 | typename _ForwardIterator, typename _Allocator> |
515 | inline _ForwardIterator |
516 | __uninitialized_move_copy(_InputIterator1 __first1, |
517 | _InputIterator1 __last1, |
518 | _InputIterator2 __first2, |
519 | _InputIterator2 __last2, |
520 | _ForwardIterator __result, |
521 | _Allocator& __alloc) |
522 | { |
523 | _ForwardIterator __mid = std::__uninitialized_move_a(__first1, __last1, |
524 | __result, |
525 | __alloc); |
526 | __try |
527 | { |
528 | return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc); |
529 | } |
530 | __catch(...) |
531 | { |
532 | std::_Destroy(__result, __mid, __alloc); |
533 | __throw_exception_again; |
534 | } |
535 | } |
536 | |
537 | // __uninitialized_fill_move |
538 | // Fills [result, mid) with x, and moves [first, last) into |
539 | // [mid, mid + (last - first)). |
540 | template<typename _ForwardIterator, typename _Tp, typename _InputIterator, |
541 | typename _Allocator> |
542 | inline _ForwardIterator |
543 | __uninitialized_fill_move(_ForwardIterator __result, _ForwardIterator __mid, |
544 | const _Tp& __x, _InputIterator __first, |
545 | _InputIterator __last, _Allocator& __alloc) |
546 | { |
547 | std::__uninitialized_fill_a(__result, __mid, __x, __alloc); |
548 | __try |
549 | { |
550 | return std::__uninitialized_move_a(__first, __last, __mid, __alloc); |
551 | } |
552 | __catch(...) |
553 | { |
554 | std::_Destroy(__result, __mid, __alloc); |
555 | __throw_exception_again; |
556 | } |
557 | } |
558 | |
559 | // __uninitialized_move_fill |
560 | // Moves [first1, last1) into [first2, first2 + (last1 - first1)), and |
561 | // fills [first2 + (last1 - first1), last2) with x. |
562 | template<typename _InputIterator, typename _ForwardIterator, typename _Tp, |
563 | typename _Allocator> |
564 | inline void |
565 | __uninitialized_move_fill(_InputIterator __first1, _InputIterator __last1, |
566 | _ForwardIterator __first2, |
567 | _ForwardIterator __last2, const _Tp& __x, |
568 | _Allocator& __alloc) |
569 | { |
570 | _ForwardIterator __mid2 = std::__uninitialized_move_a(__first1, __last1, |
571 | __first2, |
572 | __alloc); |
573 | __try |
574 | { |
575 | std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc); |
576 | } |
577 | __catch(...) |
578 | { |
579 | std::_Destroy(__first2, __mid2, __alloc); |
580 | __throw_exception_again; |
581 | } |
582 | } |
583 | |
584 | /// @endcond |
585 | |
586 | #if __cplusplus >= 201103L |
587 | /// @cond undocumented |
588 | |
589 | // Extensions: __uninitialized_default, __uninitialized_default_n, |
590 | // __uninitialized_default_a, __uninitialized_default_n_a. |
591 | |
592 | template<bool _TrivialValueType> |
593 | struct __uninitialized_default_1 |
594 | { |
595 | template<typename _ForwardIterator> |
596 | static void |
597 | __uninit_default(_ForwardIterator __first, _ForwardIterator __last) |
598 | { |
599 | _ForwardIterator __cur = __first; |
600 | __try |
601 | { |
602 | for (; __cur != __last; ++__cur) |
603 | std::_Construct(std::__addressof(*__cur)); |
604 | } |
605 | __catch(...) |
606 | { |
607 | std::_Destroy(__first, __cur); |
608 | __throw_exception_again; |
609 | } |
610 | } |
611 | }; |
612 | |
613 | template<> |
614 | struct __uninitialized_default_1<true> |
615 | { |
616 | template<typename _ForwardIterator> |
617 | static void |
618 | __uninit_default(_ForwardIterator __first, _ForwardIterator __last) |
619 | { |
620 | if (__first == __last) |
621 | return; |
622 | |
623 | typename iterator_traits<_ForwardIterator>::value_type* __val |
624 | = std::__addressof(*__first); |
625 | std::_Construct(__val); |
626 | if (++__first != __last) |
627 | std::fill(__first, __last, *__val); |
628 | } |
629 | }; |
630 | |
631 | template<bool _TrivialValueType> |
632 | struct __uninitialized_default_n_1 |
633 | { |
634 | template<typename _ForwardIterator, typename _Size> |
635 | _GLIBCXX20_CONSTEXPR |
636 | static _ForwardIterator |
637 | __uninit_default_n(_ForwardIterator __first, _Size __n) |
638 | { |
639 | _ForwardIterator __cur = __first; |
640 | __try |
641 | { |
642 | for (; __n > 0; --__n, (void) ++__cur) |
643 | std::_Construct(std::__addressof(*__cur)); |
644 | return __cur; |
645 | } |
646 | __catch(...) |
647 | { |
648 | std::_Destroy(__first, __cur); |
649 | __throw_exception_again; |
650 | } |
651 | } |
652 | }; |
653 | |
654 | template<> |
655 | struct __uninitialized_default_n_1<true> |
656 | { |
657 | template<typename _ForwardIterator, typename _Size> |
658 | _GLIBCXX20_CONSTEXPR |
659 | static _ForwardIterator |
660 | __uninit_default_n(_ForwardIterator __first, _Size __n) |
661 | { |
662 | if (__n > 0) |
663 | { |
664 | typename iterator_traits<_ForwardIterator>::value_type* __val |
665 | = std::__addressof(*__first); |
666 | std::_Construct(__val); |
667 | ++__first; |
668 | __first = std::fill_n(__first, __n - 1, *__val); |
669 | } |
670 | return __first; |
671 | } |
672 | }; |
673 | |
674 | // __uninitialized_default |
675 | // Fills [first, last) with value-initialized value_types. |
676 | template<typename _ForwardIterator> |
677 | inline void |
678 | __uninitialized_default(_ForwardIterator __first, |
679 | _ForwardIterator __last) |
680 | { |
681 | typedef typename iterator_traits<_ForwardIterator>::value_type |
682 | _ValueType; |
683 | // trivial types can have deleted assignment |
684 | const bool __assignable = is_copy_assignable<_ValueType>::value; |
685 | |
686 | std::__uninitialized_default_1<__is_trivial(_ValueType) |
687 | && __assignable>:: |
688 | __uninit_default(__first, __last); |
689 | } |
690 | |
691 | // __uninitialized_default_n |
692 | // Fills [first, first + n) with value-initialized value_types. |
693 | template<typename _ForwardIterator, typename _Size> |
694 | _GLIBCXX20_CONSTEXPR |
695 | inline _ForwardIterator |
696 | __uninitialized_default_n(_ForwardIterator __first, _Size __n) |
697 | { |
698 | #ifdef __cpp_lib_is_constant_evaluated |
699 | if (std::is_constant_evaluated()) |
700 | return __uninitialized_default_n_1<false>:: |
701 | __uninit_default_n(__first, __n); |
702 | #endif |
703 | |
704 | typedef typename iterator_traits<_ForwardIterator>::value_type |
705 | _ValueType; |
706 | // See uninitialized_fill_n for the conditions for using std::fill_n. |
707 | constexpr bool __can_fill |
708 | = __and_<is_integral<_Size>, is_copy_assignable<_ValueType>>::value; |
709 | |
710 | return __uninitialized_default_n_1<__is_trivial(_ValueType) |
711 | && __can_fill>:: |
712 | __uninit_default_n(__first, __n); |
713 | } |
714 | |
715 | |
716 | // __uninitialized_default_a |
717 | // Fills [first, last) with value_types constructed by the allocator |
718 | // alloc, with no arguments passed to the construct call. |
719 | template<typename _ForwardIterator, typename _Allocator> |
720 | void |
721 | __uninitialized_default_a(_ForwardIterator __first, |
722 | _ForwardIterator __last, |
723 | _Allocator& __alloc) |
724 | { |
725 | _ForwardIterator __cur = __first; |
726 | __try |
727 | { |
728 | typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; |
729 | for (; __cur != __last; ++__cur) |
730 | __traits::construct(__alloc, std::__addressof(*__cur)); |
731 | } |
732 | __catch(...) |
733 | { |
734 | std::_Destroy(__first, __cur, __alloc); |
735 | __throw_exception_again; |
736 | } |
737 | } |
738 | |
739 | #if _GLIBCXX_HOSTED |
740 | template<typename _ForwardIterator, typename _Tp> |
741 | inline void |
742 | __uninitialized_default_a(_ForwardIterator __first, |
743 | _ForwardIterator __last, |
744 | allocator<_Tp>&) |
745 | { std::__uninitialized_default(__first, __last); } |
746 | #endif |
747 | |
748 | // __uninitialized_default_n_a |
749 | // Fills [first, first + n) with value_types constructed by the allocator |
750 | // alloc, with no arguments passed to the construct call. |
751 | template<typename _ForwardIterator, typename _Size, typename _Allocator> |
752 | _GLIBCXX20_CONSTEXPR _ForwardIterator |
753 | __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, |
754 | _Allocator& __alloc) |
755 | { |
756 | _ForwardIterator __cur = __first; |
757 | __try |
758 | { |
759 | typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; |
760 | for (; __n > 0; --__n, (void) ++__cur) |
761 | __traits::construct(__alloc, std::__addressof(*__cur)); |
762 | return __cur; |
763 | } |
764 | __catch(...) |
765 | { |
766 | std::_Destroy(__first, __cur, __alloc); |
767 | __throw_exception_again; |
768 | } |
769 | } |
770 | |
771 | #if _GLIBCXX_HOSTED |
772 | // __uninitialized_default_n_a specialization for std::allocator, |
773 | // which ignores the allocator and value-initializes the elements. |
774 | template<typename _ForwardIterator, typename _Size, typename _Tp> |
775 | _GLIBCXX20_CONSTEXPR |
776 | inline _ForwardIterator |
777 | __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, |
778 | allocator<_Tp>&) |
779 | { return std::__uninitialized_default_n(__first, __n); } |
780 | #endif |
781 | |
782 | template<bool _TrivialValueType> |
783 | struct __uninitialized_default_novalue_1 |
784 | { |
785 | template<typename _ForwardIterator> |
786 | static void |
787 | __uninit_default_novalue(_ForwardIterator __first, |
788 | _ForwardIterator __last) |
789 | { |
790 | _ForwardIterator __cur = __first; |
791 | __try |
792 | { |
793 | for (; __cur != __last; ++__cur) |
794 | std::_Construct_novalue(std::__addressof(*__cur)); |
795 | } |
796 | __catch(...) |
797 | { |
798 | std::_Destroy(__first, __cur); |
799 | __throw_exception_again; |
800 | } |
801 | } |
802 | }; |
803 | |
804 | template<> |
805 | struct __uninitialized_default_novalue_1<true> |
806 | { |
807 | template<typename _ForwardIterator> |
808 | static void |
809 | __uninit_default_novalue(_ForwardIterator, _ForwardIterator) |
810 | { |
811 | } |
812 | }; |
813 | |
814 | template<bool _TrivialValueType> |
815 | struct __uninitialized_default_novalue_n_1 |
816 | { |
817 | template<typename _ForwardIterator, typename _Size> |
818 | static _ForwardIterator |
819 | __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) |
820 | { |
821 | _ForwardIterator __cur = __first; |
822 | __try |
823 | { |
824 | for (; __n > 0; --__n, (void) ++__cur) |
825 | std::_Construct_novalue(std::__addressof(*__cur)); |
826 | return __cur; |
827 | } |
828 | __catch(...) |
829 | { |
830 | std::_Destroy(__first, __cur); |
831 | __throw_exception_again; |
832 | } |
833 | } |
834 | }; |
835 | |
836 | template<> |
837 | struct __uninitialized_default_novalue_n_1<true> |
838 | { |
839 | template<typename _ForwardIterator, typename _Size> |
840 | static _ForwardIterator |
841 | __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) |
842 | { return std::next(__first, __n); } |
843 | }; |
844 | |
845 | // __uninitialized_default_novalue |
846 | // Fills [first, last) with default-initialized value_types. |
847 | template<typename _ForwardIterator> |
848 | inline void |
849 | __uninitialized_default_novalue(_ForwardIterator __first, |
850 | _ForwardIterator __last) |
851 | { |
852 | typedef typename iterator_traits<_ForwardIterator>::value_type |
853 | _ValueType; |
854 | |
855 | std::__uninitialized_default_novalue_1< |
856 | is_trivially_default_constructible<_ValueType>::value>:: |
857 | __uninit_default_novalue(__first, __last); |
858 | } |
859 | |
860 | // __uninitialized_default_novalue_n |
861 | // Fills [first, first + n) with default-initialized value_types. |
862 | template<typename _ForwardIterator, typename _Size> |
863 | inline _ForwardIterator |
864 | __uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n) |
865 | { |
866 | typedef typename iterator_traits<_ForwardIterator>::value_type |
867 | _ValueType; |
868 | |
869 | return __uninitialized_default_novalue_n_1< |
870 | is_trivially_default_constructible<_ValueType>::value>:: |
871 | __uninit_default_novalue_n(__first, __n); |
872 | } |
873 | |
874 | template<typename _InputIterator, typename _Size, |
875 | typename _ForwardIterator> |
876 | _ForwardIterator |
877 | __uninitialized_copy_n(_InputIterator __first, _Size __n, |
878 | _ForwardIterator __result, input_iterator_tag) |
879 | { |
880 | _ForwardIterator __cur = __result; |
881 | __try |
882 | { |
883 | for (; __n > 0; --__n, (void) ++__first, ++__cur) |
884 | std::_Construct(std::__addressof(*__cur), *__first); |
885 | return __cur; |
886 | } |
887 | __catch(...) |
888 | { |
889 | std::_Destroy(__result, __cur); |
890 | __throw_exception_again; |
891 | } |
892 | } |
893 | |
894 | template<typename _RandomAccessIterator, typename _Size, |
895 | typename _ForwardIterator> |
896 | inline _ForwardIterator |
897 | __uninitialized_copy_n(_RandomAccessIterator __first, _Size __n, |
898 | _ForwardIterator __result, |
899 | random_access_iterator_tag) |
900 | { return std::uninitialized_copy(__first, __first + __n, __result); } |
901 | |
902 | template<typename _InputIterator, typename _Size, |
903 | typename _ForwardIterator> |
904 | pair<_InputIterator, _ForwardIterator> |
905 | __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, |
906 | _ForwardIterator __result, input_iterator_tag) |
907 | { |
908 | _ForwardIterator __cur = __result; |
909 | __try |
910 | { |
911 | for (; __n > 0; --__n, (void) ++__first, ++__cur) |
912 | std::_Construct(std::__addressof(*__cur), *__first); |
913 | return {__first, __cur}; |
914 | } |
915 | __catch(...) |
916 | { |
917 | std::_Destroy(__result, __cur); |
918 | __throw_exception_again; |
919 | } |
920 | } |
921 | |
922 | template<typename _RandomAccessIterator, typename _Size, |
923 | typename _ForwardIterator> |
924 | inline pair<_RandomAccessIterator, _ForwardIterator> |
925 | __uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n, |
926 | _ForwardIterator __result, |
927 | random_access_iterator_tag) |
928 | { |
929 | auto __second_res = uninitialized_copy(__first, __first + __n, __result); |
930 | auto __first_res = std::next(__first, __n); |
931 | return {__first_res, __second_res}; |
932 | } |
933 | |
934 | /// @endcond |
935 | |
936 | /** |
937 | * @brief Copies the range [first,first+n) into result. |
938 | * @param __first An input iterator. |
939 | * @param __n The number of elements to copy. |
940 | * @param __result An output iterator. |
941 | * @return __result + __n |
942 | * @since C++11 |
943 | * |
944 | * Like copy_n(), but does not require an initialized output range. |
945 | */ |
946 | template<typename _InputIterator, typename _Size, typename _ForwardIterator> |
947 | inline _ForwardIterator |
948 | uninitialized_copy_n(_InputIterator __first, _Size __n, |
949 | _ForwardIterator __result) |
950 | { return std::__uninitialized_copy_n(__first, __n, __result, |
951 | std::__iterator_category(__first)); } |
952 | |
953 | /// @cond undocumented |
954 | template<typename _InputIterator, typename _Size, typename _ForwardIterator> |
955 | inline pair<_InputIterator, _ForwardIterator> |
956 | __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, |
957 | _ForwardIterator __result) |
958 | { |
959 | return |
960 | std::__uninitialized_copy_n_pair(__first, __n, __result, |
961 | std::__iterator_category(__first)); |
962 | } |
963 | /// @endcond |
964 | #endif |
965 | |
966 | #ifdef __glibcxx_raw_memory_algorithms // C++ >= 17 |
967 | /** |
968 | * @brief Default-initializes objects in the range [first,last). |
969 | * @param __first A forward iterator. |
970 | * @param __last A forward iterator. |
971 | * @since C++17 |
972 | */ |
973 | template <typename _ForwardIterator> |
974 | inline void |
975 | uninitialized_default_construct(_ForwardIterator __first, |
976 | _ForwardIterator __last) |
977 | { |
978 | __uninitialized_default_novalue(__first, __last); |
979 | } |
980 | |
981 | /** |
982 | * @brief Default-initializes objects in the range [first,first+count). |
983 | * @param __first A forward iterator. |
984 | * @param __count The number of objects to construct. |
985 | * @return __first + __count |
986 | * @since C++17 |
987 | */ |
988 | template <typename _ForwardIterator, typename _Size> |
989 | inline _ForwardIterator |
990 | uninitialized_default_construct_n(_ForwardIterator __first, _Size __count) |
991 | { |
992 | return __uninitialized_default_novalue_n(__first, __count); |
993 | } |
994 | |
995 | /** |
996 | * @brief Value-initializes objects in the range [first,last). |
997 | * @param __first A forward iterator. |
998 | * @param __last A forward iterator. |
999 | * @since C++17 |
1000 | */ |
1001 | template <typename _ForwardIterator> |
1002 | inline void |
1003 | uninitialized_value_construct(_ForwardIterator __first, |
1004 | _ForwardIterator __last) |
1005 | { |
1006 | return __uninitialized_default(__first, __last); |
1007 | } |
1008 | |
1009 | /** |
1010 | * @brief Value-initializes objects in the range [first,first+count). |
1011 | * @param __first A forward iterator. |
1012 | * @param __count The number of objects to construct. |
1013 | * @return __result + __count |
1014 | * @since C++17 |
1015 | */ |
1016 | template <typename _ForwardIterator, typename _Size> |
1017 | inline _ForwardIterator |
1018 | uninitialized_value_construct_n(_ForwardIterator __first, _Size __count) |
1019 | { |
1020 | return __uninitialized_default_n(__first, __count); |
1021 | } |
1022 | |
1023 | /** |
1024 | * @brief Move-construct from the range [first,last) into result. |
1025 | * @param __first An input iterator. |
1026 | * @param __last An input iterator. |
1027 | * @param __result An output iterator. |
1028 | * @return __result + (__first - __last) |
1029 | * @since C++17 |
1030 | */ |
1031 | template <typename _InputIterator, typename _ForwardIterator> |
1032 | inline _ForwardIterator |
1033 | uninitialized_move(_InputIterator __first, _InputIterator __last, |
1034 | _ForwardIterator __result) |
1035 | { |
1036 | return std::uninitialized_copy |
1037 | (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), |
1038 | _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result); |
1039 | } |
1040 | |
1041 | /** |
1042 | * @brief Move-construct from the range [first,first+count) into result. |
1043 | * @param __first An input iterator. |
1044 | * @param __count The number of objects to initialize. |
1045 | * @param __result An output iterator. |
1046 | * @return __result + __count |
1047 | * @since C++17 |
1048 | */ |
1049 | template <typename _InputIterator, typename _Size, typename _ForwardIterator> |
1050 | inline pair<_InputIterator, _ForwardIterator> |
1051 | uninitialized_move_n(_InputIterator __first, _Size __count, |
1052 | _ForwardIterator __result) |
1053 | { |
1054 | auto __res = std::__uninitialized_copy_n_pair |
1055 | (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), |
1056 | __count, __result); |
1057 | return {__res.first.base(), __res.second}; |
1058 | } |
1059 | #endif // __glibcxx_raw_memory_algorithms |
1060 | |
1061 | #if __cplusplus >= 201103L |
1062 | /// @cond undocumented |
1063 | |
1064 | template<typename _Tp, typename _Up, typename _Allocator> |
1065 | _GLIBCXX20_CONSTEXPR |
1066 | inline void |
1067 | __relocate_object_a(_Tp* __restrict __dest, _Up* __restrict __orig, |
1068 | _Allocator& __alloc) |
1069 | noexcept(noexcept(std::allocator_traits<_Allocator>::construct(__alloc, |
1070 | __dest, std::move(*__orig))) |
1071 | && noexcept(std::allocator_traits<_Allocator>::destroy( |
1072 | __alloc, std::__addressof(*__orig)))) |
1073 | { |
1074 | typedef std::allocator_traits<_Allocator> __traits; |
1075 | __traits::construct(__alloc, __dest, std::move(*__orig)); |
1076 | __traits::destroy(__alloc, std::__addressof(*__orig)); |
1077 | } |
1078 | |
1079 | // This class may be specialized for specific types. |
1080 | // Also known as is_trivially_relocatable. |
1081 | template<typename _Tp, typename = void> |
1082 | struct __is_bitwise_relocatable |
1083 | : is_trivial<_Tp> { }; |
1084 | |
1085 | template <typename _InputIterator, typename _ForwardIterator, |
1086 | typename _Allocator> |
1087 | _GLIBCXX20_CONSTEXPR |
1088 | inline _ForwardIterator |
1089 | __relocate_a_1(_InputIterator __first, _InputIterator __last, |
1090 | _ForwardIterator __result, _Allocator& __alloc) |
1091 | noexcept(noexcept(std::__relocate_object_a(std::addressof(*__result), |
1092 | std::addressof(*__first), |
1093 | __alloc))) |
1094 | { |
1095 | typedef typename iterator_traits<_InputIterator>::value_type |
1096 | _ValueType; |
1097 | typedef typename iterator_traits<_ForwardIterator>::value_type |
1098 | _ValueType2; |
1099 | static_assert(std::is_same<_ValueType, _ValueType2>::value, |
1100 | "relocation is only possible for values of the same type" ); |
1101 | _ForwardIterator __cur = __result; |
1102 | for (; __first != __last; ++__first, (void)++__cur) |
1103 | std::__relocate_object_a(std::__addressof(*__cur), |
1104 | std::__addressof(*__first), __alloc); |
1105 | return __cur; |
1106 | } |
1107 | |
1108 | #if _GLIBCXX_HOSTED |
1109 | template <typename _Tp, typename _Up> |
1110 | _GLIBCXX20_CONSTEXPR |
1111 | inline __enable_if_t<std::__is_bitwise_relocatable<_Tp>::value, _Tp*> |
1112 | __relocate_a_1(_Tp* __first, _Tp* __last, |
1113 | _Tp* __result, |
1114 | [[__maybe_unused__]] allocator<_Up>& __alloc) noexcept |
1115 | { |
1116 | ptrdiff_t __count = __last - __first; |
1117 | if (__count > 0) |
1118 | { |
1119 | #ifdef __cpp_lib_is_constant_evaluated |
1120 | if (std::is_constant_evaluated()) |
1121 | { |
1122 | // Can't use memcpy. Wrap the pointer so that __relocate_a_1 |
1123 | // resolves to the non-trivial overload above. |
1124 | __gnu_cxx::__normal_iterator<_Tp*, void> __out(__result); |
1125 | __out = std::__relocate_a_1(__first, __last, __out, __alloc); |
1126 | return __out.base(); |
1127 | } |
1128 | #endif |
1129 | __builtin_memcpy(__result, __first, __count * sizeof(_Tp)); |
1130 | } |
1131 | return __result + __count; |
1132 | } |
1133 | #endif |
1134 | |
1135 | template <typename _InputIterator, typename _ForwardIterator, |
1136 | typename _Allocator> |
1137 | _GLIBCXX20_CONSTEXPR |
1138 | inline _ForwardIterator |
1139 | __relocate_a(_InputIterator __first, _InputIterator __last, |
1140 | _ForwardIterator __result, _Allocator& __alloc) |
1141 | noexcept(noexcept(__relocate_a_1(std::__niter_base(__first), |
1142 | std::__niter_base(__last), |
1143 | std::__niter_base(__result), __alloc))) |
1144 | { |
1145 | return std::__relocate_a_1(std::__niter_base(__first), |
1146 | std::__niter_base(__last), |
1147 | std::__niter_base(__result), __alloc); |
1148 | } |
1149 | |
1150 | /// @endcond |
1151 | #endif // C++11 |
1152 | |
1153 | /// @} group memory |
1154 | |
1155 | _GLIBCXX_END_NAMESPACE_VERSION |
1156 | } // namespace |
1157 | |
1158 | #endif /* _STL_UNINITIALIZED_H */ |
1159 | |