1 | // Raw memory manipulators -*- C++ -*- |
2 | |
3 | // Copyright (C) 2020-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 | /** @file bits/ranges_uninitialized.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{memory} |
28 | */ |
29 | |
30 | #ifndef _RANGES_UNINITIALIZED_H |
31 | #define _RANGES_UNINITIALIZED_H 1 |
32 | |
33 | #if __cplusplus > 201703L |
34 | #if __cpp_lib_concepts |
35 | |
36 | #include <bits/ranges_algobase.h> |
37 | |
38 | namespace std _GLIBCXX_VISIBILITY(default) |
39 | { |
40 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
41 | namespace ranges |
42 | { |
43 | namespace __detail |
44 | { |
45 | template<typename _Tp> |
46 | constexpr void* |
47 | __voidify(_Tp& __obj) noexcept |
48 | { |
49 | return const_cast<void*> |
50 | (static_cast<const volatile void*>(std::__addressof(__obj))); |
51 | } |
52 | |
53 | template<typename _Iter> |
54 | concept __nothrow_input_iterator |
55 | = (input_iterator<_Iter> |
56 | && is_lvalue_reference_v<iter_reference_t<_Iter>> |
57 | && same_as<remove_cvref_t<iter_reference_t<_Iter>>, |
58 | iter_value_t<_Iter>>); |
59 | |
60 | template<typename _Sent, typename _Iter> |
61 | concept __nothrow_sentinel = sentinel_for<_Sent, _Iter>; |
62 | |
63 | template<typename _Range> |
64 | concept __nothrow_input_range |
65 | = (range<_Range> |
66 | && __nothrow_input_iterator<iterator_t<_Range>> |
67 | && __nothrow_sentinel<sentinel_t<_Range>, iterator_t<_Range>>); |
68 | |
69 | template<typename _Iter> |
70 | concept __nothrow_forward_iterator |
71 | = (__nothrow_input_iterator<_Iter> |
72 | && forward_iterator<_Iter> |
73 | && __nothrow_sentinel<_Iter, _Iter>); |
74 | |
75 | template<typename _Range> |
76 | concept __nothrow_forward_range |
77 | = (__nothrow_input_range<_Range> |
78 | && __nothrow_forward_iterator<iterator_t<_Range>>); |
79 | } // namespace __detail |
80 | |
81 | struct __destroy_fn |
82 | { |
83 | template<__detail::__nothrow_input_iterator _Iter, |
84 | __detail::__nothrow_sentinel<_Iter> _Sent> |
85 | requires destructible<iter_value_t<_Iter>> |
86 | constexpr _Iter |
87 | operator()(_Iter __first, _Sent __last) const noexcept; |
88 | |
89 | template<__detail::__nothrow_input_range _Range> |
90 | requires destructible<range_value_t<_Range>> |
91 | constexpr borrowed_iterator_t<_Range> |
92 | operator()(_Range&& __r) const noexcept; |
93 | }; |
94 | |
95 | inline constexpr __destroy_fn destroy{}; |
96 | |
97 | namespace __detail |
98 | { |
99 | template<typename _Iter> |
100 | requires destructible<iter_value_t<_Iter>> |
101 | struct _DestroyGuard |
102 | { |
103 | private: |
104 | _Iter _M_first; |
105 | const _Iter* _M_cur; |
106 | |
107 | public: |
108 | explicit |
109 | _DestroyGuard(const _Iter& __iter) |
110 | : _M_first(__iter), _M_cur(std::__addressof(__iter)) |
111 | { } |
112 | |
113 | void |
114 | release() noexcept |
115 | { _M_cur = nullptr; } |
116 | |
117 | ~_DestroyGuard() |
118 | { |
119 | if (_M_cur != nullptr) |
120 | ranges::destroy(std::move(_M_first), *_M_cur); |
121 | } |
122 | }; |
123 | |
124 | template<typename _Iter> |
125 | requires destructible<iter_value_t<_Iter>> |
126 | && is_trivially_destructible_v<iter_value_t<_Iter>> |
127 | struct _DestroyGuard<_Iter> |
128 | { |
129 | explicit |
130 | _DestroyGuard(const _Iter&) |
131 | { } |
132 | |
133 | void |
134 | release() noexcept |
135 | { } |
136 | }; |
137 | } // namespace __detail |
138 | |
139 | struct __uninitialized_default_construct_fn |
140 | { |
141 | template<__detail::__nothrow_forward_iterator _Iter, |
142 | __detail::__nothrow_sentinel<_Iter> _Sent> |
143 | requires default_initializable<iter_value_t<_Iter>> |
144 | _Iter |
145 | operator()(_Iter __first, _Sent __last) const |
146 | { |
147 | using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; |
148 | if constexpr (is_trivially_default_constructible_v<_ValueType>) |
149 | return ranges::next(__first, __last); |
150 | else |
151 | { |
152 | auto __guard = __detail::_DestroyGuard(__first); |
153 | for (; __first != __last; ++__first) |
154 | ::new (__detail::__voidify(*__first)) _ValueType; |
155 | __guard.release(); |
156 | return __first; |
157 | } |
158 | } |
159 | |
160 | template<__detail::__nothrow_forward_range _Range> |
161 | requires default_initializable<range_value_t<_Range>> |
162 | borrowed_iterator_t<_Range> |
163 | operator()(_Range&& __r) const |
164 | { |
165 | return (*this)(ranges::begin(__r), ranges::end(__r)); |
166 | } |
167 | }; |
168 | |
169 | inline constexpr __uninitialized_default_construct_fn |
170 | uninitialized_default_construct{}; |
171 | |
172 | struct __uninitialized_default_construct_n_fn |
173 | { |
174 | template<__detail::__nothrow_forward_iterator _Iter> |
175 | requires default_initializable<iter_value_t<_Iter>> |
176 | _Iter |
177 | operator()(_Iter __first, iter_difference_t<_Iter> __n) const |
178 | { |
179 | using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; |
180 | if constexpr (is_trivially_default_constructible_v<_ValueType>) |
181 | return ranges::next(__first, __n); |
182 | else |
183 | { |
184 | auto __guard = __detail::_DestroyGuard(__first); |
185 | for (; __n > 0; ++__first, (void) --__n) |
186 | ::new (__detail::__voidify(*__first)) _ValueType; |
187 | __guard.release(); |
188 | return __first; |
189 | } |
190 | } |
191 | }; |
192 | |
193 | inline constexpr __uninitialized_default_construct_n_fn |
194 | uninitialized_default_construct_n; |
195 | |
196 | struct __uninitialized_value_construct_fn |
197 | { |
198 | template<__detail::__nothrow_forward_iterator _Iter, |
199 | __detail::__nothrow_sentinel<_Iter> _Sent> |
200 | requires default_initializable<iter_value_t<_Iter>> |
201 | _Iter |
202 | operator()(_Iter __first, _Sent __last) const |
203 | { |
204 | using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; |
205 | if constexpr (is_trivial_v<_ValueType> |
206 | && is_copy_assignable_v<_ValueType>) |
207 | return ranges::fill(__first, __last, _ValueType()); |
208 | else |
209 | { |
210 | auto __guard = __detail::_DestroyGuard(__first); |
211 | for (; __first != __last; ++__first) |
212 | ::new (__detail::__voidify(*__first)) _ValueType(); |
213 | __guard.release(); |
214 | return __first; |
215 | } |
216 | } |
217 | |
218 | template<__detail::__nothrow_forward_range _Range> |
219 | requires default_initializable<range_value_t<_Range>> |
220 | borrowed_iterator_t<_Range> |
221 | operator()(_Range&& __r) const |
222 | { |
223 | return (*this)(ranges::begin(__r), ranges::end(__r)); |
224 | } |
225 | }; |
226 | |
227 | inline constexpr __uninitialized_value_construct_fn |
228 | uninitialized_value_construct{}; |
229 | |
230 | struct __uninitialized_value_construct_n_fn |
231 | { |
232 | template<__detail::__nothrow_forward_iterator _Iter> |
233 | requires default_initializable<iter_value_t<_Iter>> |
234 | _Iter |
235 | operator()(_Iter __first, iter_difference_t<_Iter> __n) const |
236 | { |
237 | using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; |
238 | if constexpr (is_trivial_v<_ValueType> |
239 | && is_copy_assignable_v<_ValueType>) |
240 | return ranges::fill_n(__first, __n, _ValueType()); |
241 | else |
242 | { |
243 | auto __guard = __detail::_DestroyGuard(__first); |
244 | for (; __n > 0; ++__first, (void) --__n) |
245 | ::new (__detail::__voidify(*__first)) _ValueType(); |
246 | __guard.release(); |
247 | return __first; |
248 | } |
249 | } |
250 | }; |
251 | |
252 | inline constexpr __uninitialized_value_construct_n_fn |
253 | uninitialized_value_construct_n; |
254 | |
255 | template<typename _Iter, typename _Out> |
256 | using uninitialized_copy_result = in_out_result<_Iter, _Out>; |
257 | |
258 | struct __uninitialized_copy_fn |
259 | { |
260 | template<input_iterator _Iter, sentinel_for<_Iter> _ISent, |
261 | __detail::__nothrow_forward_iterator _Out, |
262 | __detail::__nothrow_sentinel<_Out> _OSent> |
263 | requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>> |
264 | uninitialized_copy_result<_Iter, _Out> |
265 | operator()(_Iter __ifirst, _ISent __ilast, |
266 | _Out __ofirst, _OSent __olast) const |
267 | { |
268 | using _OutType = remove_reference_t<iter_reference_t<_Out>>; |
269 | if constexpr (sized_sentinel_for<_ISent, _Iter> |
270 | && sized_sentinel_for<_OSent, _Out> |
271 | && is_trivial_v<_OutType> |
272 | && is_nothrow_assignable_v<_OutType&, |
273 | iter_reference_t<_Iter>>) |
274 | { |
275 | auto __d1 = __ilast - __ifirst; |
276 | auto __d2 = __olast - __ofirst; |
277 | return ranges::copy_n(std::move(__ifirst), std::min(__d1, __d2), |
278 | __ofirst); |
279 | } |
280 | else |
281 | { |
282 | auto __guard = __detail::_DestroyGuard(__ofirst); |
283 | for (; __ifirst != __ilast && __ofirst != __olast; |
284 | ++__ofirst, (void)++__ifirst) |
285 | ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); |
286 | __guard.release(); |
287 | return {std::move(__ifirst), __ofirst}; |
288 | } |
289 | } |
290 | |
291 | template<input_range _IRange, __detail::__nothrow_forward_range _ORange> |
292 | requires constructible_from<range_value_t<_ORange>, |
293 | range_reference_t<_IRange>> |
294 | uninitialized_copy_result<borrowed_iterator_t<_IRange>, |
295 | borrowed_iterator_t<_ORange>> |
296 | operator()(_IRange&& __inr, _ORange&& __outr) const |
297 | { |
298 | return (*this)(ranges::begin(__inr), ranges::end(__inr), |
299 | ranges::begin(__outr), ranges::end(__outr)); |
300 | } |
301 | }; |
302 | |
303 | inline constexpr __uninitialized_copy_fn uninitialized_copy{}; |
304 | |
305 | template<typename _Iter, typename _Out> |
306 | using uninitialized_copy_n_result = in_out_result<_Iter, _Out>; |
307 | |
308 | struct __uninitialized_copy_n_fn |
309 | { |
310 | template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out, |
311 | __detail::__nothrow_sentinel<_Out> _Sent> |
312 | requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>> |
313 | uninitialized_copy_n_result<_Iter, _Out> |
314 | operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, |
315 | _Out __ofirst, _Sent __olast) const |
316 | { |
317 | using _OutType = remove_reference_t<iter_reference_t<_Out>>; |
318 | if constexpr (sized_sentinel_for<_Sent, _Out> |
319 | && is_trivial_v<_OutType> |
320 | && is_nothrow_assignable_v<_OutType&, |
321 | iter_reference_t<_Iter>>) |
322 | { |
323 | auto __d = __olast - __ofirst; |
324 | return ranges::copy_n(std::move(__ifirst), std::min(__n, __d), |
325 | __ofirst); |
326 | } |
327 | else |
328 | { |
329 | auto __guard = __detail::_DestroyGuard(__ofirst); |
330 | for (; __n > 0 && __ofirst != __olast; |
331 | ++__ofirst, (void)++__ifirst, (void)--__n) |
332 | ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); |
333 | __guard.release(); |
334 | return {std::move(__ifirst), __ofirst}; |
335 | } |
336 | } |
337 | }; |
338 | |
339 | inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{}; |
340 | |
341 | template<typename _Iter, typename _Out> |
342 | using uninitialized_move_result = in_out_result<_Iter, _Out>; |
343 | |
344 | struct __uninitialized_move_fn |
345 | { |
346 | template<input_iterator _Iter, sentinel_for<_Iter> _ISent, |
347 | __detail::__nothrow_forward_iterator _Out, |
348 | __detail::__nothrow_sentinel<_Out> _OSent> |
349 | requires constructible_from<iter_value_t<_Out>, |
350 | iter_rvalue_reference_t<_Iter>> |
351 | uninitialized_move_result<_Iter, _Out> |
352 | operator()(_Iter __ifirst, _ISent __ilast, |
353 | _Out __ofirst, _OSent __olast) const |
354 | { |
355 | using _OutType = remove_reference_t<iter_reference_t<_Out>>; |
356 | if constexpr (sized_sentinel_for<_ISent, _Iter> |
357 | && sized_sentinel_for<_OSent, _Out> |
358 | && is_trivial_v<_OutType> |
359 | && is_nothrow_assignable_v<_OutType&, |
360 | iter_rvalue_reference_t<_Iter>>) |
361 | { |
362 | auto __d1 = __ilast - __ifirst; |
363 | auto __d2 = __olast - __ofirst; |
364 | auto [__in, __out] |
365 | = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)), |
366 | std::min(__d1, __d2), __ofirst); |
367 | return {std::move(__in).base(), __out}; |
368 | } |
369 | else |
370 | { |
371 | auto __guard = __detail::_DestroyGuard(__ofirst); |
372 | for (; __ifirst != __ilast && __ofirst != __olast; |
373 | ++__ofirst, (void)++__ifirst) |
374 | ::new (__detail::__voidify(*__ofirst)) |
375 | _OutType(ranges::iter_move(__ifirst)); |
376 | __guard.release(); |
377 | return {std::move(__ifirst), __ofirst}; |
378 | } |
379 | } |
380 | |
381 | template<input_range _IRange, __detail::__nothrow_forward_range _ORange> |
382 | requires constructible_from<range_value_t<_ORange>, |
383 | range_rvalue_reference_t<_IRange>> |
384 | uninitialized_move_result<borrowed_iterator_t<_IRange>, |
385 | borrowed_iterator_t<_ORange>> |
386 | operator()(_IRange&& __inr, _ORange&& __outr) const |
387 | { |
388 | return (*this)(ranges::begin(__inr), ranges::end(__inr), |
389 | ranges::begin(__outr), ranges::end(__outr)); |
390 | } |
391 | }; |
392 | |
393 | inline constexpr __uninitialized_move_fn uninitialized_move{}; |
394 | |
395 | template<typename _Iter, typename _Out> |
396 | using uninitialized_move_n_result = in_out_result<_Iter, _Out>; |
397 | |
398 | struct __uninitialized_move_n_fn |
399 | { |
400 | template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out, |
401 | __detail::__nothrow_sentinel<_Out> _Sent> |
402 | requires constructible_from<iter_value_t<_Out>, |
403 | iter_rvalue_reference_t<_Iter>> |
404 | uninitialized_move_n_result<_Iter, _Out> |
405 | operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, |
406 | _Out __ofirst, _Sent __olast) const |
407 | { |
408 | using _OutType = remove_reference_t<iter_reference_t<_Out>>; |
409 | if constexpr (sized_sentinel_for<_Sent, _Out> |
410 | && is_trivial_v<_OutType> |
411 | && is_nothrow_assignable_v<_OutType&, |
412 | iter_rvalue_reference_t<_Iter>>) |
413 | { |
414 | auto __d = __olast - __ofirst; |
415 | auto [__in, __out] |
416 | = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)), |
417 | std::min(__n, __d), __ofirst); |
418 | return {std::move(__in).base(), __out}; |
419 | } |
420 | else |
421 | { |
422 | auto __guard = __detail::_DestroyGuard(__ofirst); |
423 | for (; __n > 0 && __ofirst != __olast; |
424 | ++__ofirst, (void)++__ifirst, (void)--__n) |
425 | ::new (__detail::__voidify(*__ofirst)) |
426 | _OutType(ranges::iter_move(__ifirst)); |
427 | __guard.release(); |
428 | return {std::move(__ifirst), __ofirst}; |
429 | } |
430 | } |
431 | }; |
432 | |
433 | inline constexpr __uninitialized_move_n_fn uninitialized_move_n{}; |
434 | |
435 | struct __uninitialized_fill_fn |
436 | { |
437 | template<__detail::__nothrow_forward_iterator _Iter, |
438 | __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp> |
439 | requires constructible_from<iter_value_t<_Iter>, const _Tp&> |
440 | _Iter |
441 | operator()(_Iter __first, _Sent __last, const _Tp& __x) const |
442 | { |
443 | using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; |
444 | if constexpr (is_trivial_v<_ValueType> |
445 | && is_nothrow_assignable_v<_ValueType&, const _Tp&>) |
446 | return ranges::fill(__first, __last, __x); |
447 | else |
448 | { |
449 | auto __guard = __detail::_DestroyGuard(__first); |
450 | for (; __first != __last; ++__first) |
451 | ::new (__detail::__voidify(*__first)) _ValueType(__x); |
452 | __guard.release(); |
453 | return __first; |
454 | } |
455 | } |
456 | |
457 | template<__detail::__nothrow_forward_range _Range, typename _Tp> |
458 | requires constructible_from<range_value_t<_Range>, const _Tp&> |
459 | borrowed_iterator_t<_Range> |
460 | operator()(_Range&& __r, const _Tp& __x) const |
461 | { |
462 | return (*this)(ranges::begin(__r), ranges::end(__r), __x); |
463 | } |
464 | }; |
465 | |
466 | inline constexpr __uninitialized_fill_fn uninitialized_fill{}; |
467 | |
468 | struct __uninitialized_fill_n_fn |
469 | { |
470 | template<__detail::__nothrow_forward_iterator _Iter, typename _Tp> |
471 | requires constructible_from<iter_value_t<_Iter>, const _Tp&> |
472 | _Iter |
473 | operator()(_Iter __first, iter_difference_t<_Iter> __n, |
474 | const _Tp& __x) const |
475 | { |
476 | using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; |
477 | if constexpr (is_trivial_v<_ValueType> |
478 | && is_nothrow_assignable_v<_ValueType&, const _Tp&>) |
479 | return ranges::fill_n(__first, __n, __x); |
480 | else |
481 | { |
482 | auto __guard = __detail::_DestroyGuard(__first); |
483 | for (; __n > 0; ++__first, (void)--__n) |
484 | ::new (__detail::__voidify(*__first)) _ValueType(__x); |
485 | __guard.release(); |
486 | return __first; |
487 | } |
488 | } |
489 | }; |
490 | |
491 | inline constexpr __uninitialized_fill_n_fn uninitialized_fill_n{}; |
492 | |
493 | struct __construct_at_fn |
494 | { |
495 | template<typename _Tp, typename... _Args> |
496 | requires requires { |
497 | ::new (std::declval<void*>()) _Tp(std::declval<_Args>()...); |
498 | } |
499 | constexpr _Tp* |
500 | operator()(_Tp* __location, _Args&&... __args) const |
501 | noexcept(noexcept(std::construct_at(__location, |
502 | std::forward<_Args>(__args)...))) |
503 | { |
504 | return std::construct_at(__location, |
505 | std::forward<_Args>(__args)...); |
506 | } |
507 | }; |
508 | |
509 | inline constexpr __construct_at_fn construct_at{}; |
510 | |
511 | struct __destroy_at_fn |
512 | { |
513 | template<destructible _Tp> |
514 | constexpr void |
515 | operator()(_Tp* __location) const noexcept |
516 | { |
517 | if constexpr (is_array_v<_Tp>) |
518 | ranges::destroy(ranges::begin(*__location), ranges::end(*__location)); |
519 | else |
520 | __location->~_Tp(); |
521 | } |
522 | }; |
523 | |
524 | inline constexpr __destroy_at_fn destroy_at{}; |
525 | |
526 | template<__detail::__nothrow_input_iterator _Iter, |
527 | __detail::__nothrow_sentinel<_Iter> _Sent> |
528 | requires destructible<iter_value_t<_Iter>> |
529 | constexpr _Iter |
530 | __destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept |
531 | { |
532 | if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>) |
533 | return ranges::next(std::move(__first), __last); |
534 | else |
535 | { |
536 | for (; __first != __last; ++__first) |
537 | ranges::destroy_at(std::__addressof(*__first)); |
538 | return __first; |
539 | } |
540 | } |
541 | |
542 | template<__detail::__nothrow_input_range _Range> |
543 | requires destructible<range_value_t<_Range>> |
544 | constexpr borrowed_iterator_t<_Range> |
545 | __destroy_fn::operator()(_Range&& __r) const noexcept |
546 | { |
547 | return (*this)(ranges::begin(__r), ranges::end(__r)); |
548 | } |
549 | |
550 | struct __destroy_n_fn |
551 | { |
552 | template<__detail::__nothrow_input_iterator _Iter> |
553 | requires destructible<iter_value_t<_Iter>> |
554 | constexpr _Iter |
555 | operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept |
556 | { |
557 | if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>) |
558 | return ranges::next(std::move(__first), __n); |
559 | else |
560 | { |
561 | for (; __n > 0; ++__first, (void)--__n) |
562 | ranges::destroy_at(std::__addressof(*__first)); |
563 | return __first; |
564 | } |
565 | } |
566 | }; |
567 | |
568 | inline constexpr __destroy_n_fn destroy_n{}; |
569 | } |
570 | _GLIBCXX_END_NAMESPACE_VERSION |
571 | } // namespace std |
572 | #endif // concepts |
573 | #endif // C++20 |
574 | #endif // _RANGES_UNINITIALIZED_H |
575 | |