libstdc++
ranges_uninitialized.h
Go to the documentation of this file.
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
37
38namespace std _GLIBCXX_VISIBILITY(default)
39{
40_GLIBCXX_BEGIN_NAMESPACE_VERSION
41namespace 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
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
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
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
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 __d = __ilast - __ifirst;
276 if (auto __d2 = __olast - __ofirst; __d2 < __d)
277 __d = static_cast<iter_difference_t<_Iter>>(__d2);
278 return ranges::copy_n(std::move(__ifirst), __d, __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 if (auto __d = __olast - __ofirst; __d < __n)
324 __n = static_cast<iter_difference_t<_Iter>>(__d);
325 return ranges::copy_n(std::move(__ifirst), __n, __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 __d = __ilast - __ifirst;
363 if (auto __d2 = __olast - __ofirst; __d2 < __d)
364 __d = static_cast<iter_difference_t<_Iter>>(__d2);
365 auto [__in, __out]
366 = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)),
367 __d, __ofirst);
368 return {std::move(__in).base(), __out};
369 }
370 else
371 {
372 auto __guard = __detail::_DestroyGuard(__ofirst);
373 for (; __ifirst != __ilast && __ofirst != __olast;
374 ++__ofirst, (void)++__ifirst)
375 ::new (__detail::__voidify(*__ofirst))
376 _OutType(ranges::iter_move(__ifirst));
377 __guard.release();
378 return {std::move(__ifirst), __ofirst};
379 }
380 }
381
382 template<input_range _IRange, __detail::__nothrow_forward_range _ORange>
383 requires constructible_from<range_value_t<_ORange>,
384 range_rvalue_reference_t<_IRange>>
385 uninitialized_move_result<borrowed_iterator_t<_IRange>,
386 borrowed_iterator_t<_ORange>>
387 operator()(_IRange&& __inr, _ORange&& __outr) const
388 {
389 return (*this)(ranges::begin(__inr), ranges::end(__inr),
390 ranges::begin(__outr), ranges::end(__outr));
391 }
392 };
393
394 inline constexpr __uninitialized_move_fn uninitialized_move{};
395
396 template<typename _Iter, typename _Out>
397 using uninitialized_move_n_result = in_out_result<_Iter, _Out>;
398
399 struct __uninitialized_move_n_fn
400 {
401 template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out,
402 __detail::__nothrow_sentinel<_Out> _Sent>
403 requires constructible_from<iter_value_t<_Out>,
404 iter_rvalue_reference_t<_Iter>>
405 uninitialized_move_n_result<_Iter, _Out>
406 operator()(_Iter __ifirst, iter_difference_t<_Iter> __n,
407 _Out __ofirst, _Sent __olast) const
408 {
409 using _OutType = remove_reference_t<iter_reference_t<_Out>>;
410 if constexpr (sized_sentinel_for<_Sent, _Out>
411 && is_trivial_v<_OutType>
412 && is_nothrow_assignable_v<_OutType&,
413 iter_rvalue_reference_t<_Iter>>)
414 {
415 if (auto __d = __olast - __ofirst; __d < __n)
416 __n = static_cast<iter_difference_t<_Iter>>(__d);
417 auto [__in, __out]
418 = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)),
419 __n, __ofirst);
420 return {std::move(__in).base(), __out};
421 }
422 else
423 {
424 auto __guard = __detail::_DestroyGuard(__ofirst);
425 for (; __n > 0 && __ofirst != __olast;
426 ++__ofirst, (void)++__ifirst, (void)--__n)
427 ::new (__detail::__voidify(*__ofirst))
428 _OutType(ranges::iter_move(__ifirst));
429 __guard.release();
430 return {std::move(__ifirst), __ofirst};
431 }
432 }
433 };
434
435 inline constexpr __uninitialized_move_n_fn uninitialized_move_n{};
436
437 struct __uninitialized_fill_fn
438 {
439 template<__detail::__nothrow_forward_iterator _Iter,
440 __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp>
441 requires constructible_from<iter_value_t<_Iter>, const _Tp&>
442 _Iter
443 operator()(_Iter __first, _Sent __last, const _Tp& __x) const
444 {
445 using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
446 if constexpr (is_trivial_v<_ValueType>
447 && is_nothrow_assignable_v<_ValueType&, const _Tp&>)
448 return ranges::fill(__first, __last, __x);
449 else
450 {
451 auto __guard = __detail::_DestroyGuard(__first);
452 for (; __first != __last; ++__first)
453 ::new (__detail::__voidify(*__first)) _ValueType(__x);
454 __guard.release();
455 return __first;
456 }
457 }
458
459 template<__detail::__nothrow_forward_range _Range, typename _Tp>
460 requires constructible_from<range_value_t<_Range>, const _Tp&>
461 borrowed_iterator_t<_Range>
462 operator()(_Range&& __r, const _Tp& __x) const
463 {
464 return (*this)(ranges::begin(__r), ranges::end(__r), __x);
465 }
466 };
467
468 inline constexpr __uninitialized_fill_fn uninitialized_fill{};
469
470 struct __uninitialized_fill_n_fn
471 {
472 template<__detail::__nothrow_forward_iterator _Iter, typename _Tp>
473 requires constructible_from<iter_value_t<_Iter>, const _Tp&>
474 _Iter
475 operator()(_Iter __first, iter_difference_t<_Iter> __n,
476 const _Tp& __x) const
477 {
478 using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
479 if constexpr (is_trivial_v<_ValueType>
480 && is_nothrow_assignable_v<_ValueType&, const _Tp&>)
481 return ranges::fill_n(__first, __n, __x);
482 else
483 {
484 auto __guard = __detail::_DestroyGuard(__first);
485 for (; __n > 0; ++__first, (void)--__n)
486 ::new (__detail::__voidify(*__first)) _ValueType(__x);
487 __guard.release();
488 return __first;
489 }
490 }
491 };
492
493 inline constexpr __uninitialized_fill_n_fn uninitialized_fill_n{};
494
495 struct __construct_at_fn
496 {
497 template<typename _Tp, typename... _Args>
498 requires requires {
499 ::new (std::declval<void*>()) _Tp(std::declval<_Args>()...);
500 }
501 constexpr _Tp*
502 operator()(_Tp* __location, _Args&&... __args) const
503 noexcept(noexcept(std::construct_at(__location,
504 std::forward<_Args>(__args)...)))
505 {
506 return std::construct_at(__location,
507 std::forward<_Args>(__args)...);
508 }
509 };
510
511 inline constexpr __construct_at_fn construct_at{};
512
513 struct __destroy_at_fn
514 {
515 template<destructible _Tp>
516 constexpr void
517 operator()(_Tp* __location) const noexcept
518 {
519 if constexpr (is_array_v<_Tp>)
520 ranges::destroy(ranges::begin(*__location), ranges::end(*__location));
521 else
522 __location->~_Tp();
523 }
524 };
525
526 inline constexpr __destroy_at_fn destroy_at{};
527
528 template<__detail::__nothrow_input_iterator _Iter,
529 __detail::__nothrow_sentinel<_Iter> _Sent>
530 requires destructible<iter_value_t<_Iter>>
531 constexpr _Iter
532 __destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept
533 {
534 if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
535 return ranges::next(std::move(__first), __last);
536 else
537 {
538 for (; __first != __last; ++__first)
539 ranges::destroy_at(std::__addressof(*__first));
540 return __first;
541 }
542 }
543
544 template<__detail::__nothrow_input_range _Range>
545 requires destructible<range_value_t<_Range>>
546 constexpr borrowed_iterator_t<_Range>
547 __destroy_fn::operator()(_Range&& __r) const noexcept
548 {
549 return (*this)(ranges::begin(__r), ranges::end(__r));
550 }
551
552 struct __destroy_n_fn
553 {
554 template<__detail::__nothrow_input_iterator _Iter>
555 requires destructible<iter_value_t<_Iter>>
556 constexpr _Iter
557 operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept
558 {
559 if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
560 return ranges::next(std::move(__first), __n);
561 else
562 {
563 for (; __n > 0; ++__first, (void)--__n)
564 ranges::destroy_at(std::__addressof(*__first));
565 return __first;
566 }
567 }
568 };
569
570 inline constexpr __destroy_n_fn destroy_n{};
571}
572_GLIBCXX_END_NAMESPACE_VERSION
573} // namespace std
574#endif // concepts
575#endif // C++20
576#endif // _RANGES_UNINITIALIZED_H
_ForwardIterator uninitialized_copy_n(_InputIterator __first, _Size __n, _ForwardIterator __result)
Copies the range [first,first+n) into result.
void uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp &__x)
Copies the value x into the range [first,last).
_ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __count)
Value-initializes objects in the range [first,first+count).
_ForwardIterator uninitialized_move(_InputIterator __first, _InputIterator __last, _ForwardIterator __result)
Move-construct from the range [first,last) into result.
_ForwardIterator uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp &__x)
Copies the value x into the range [first,first+n).
_ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __count)
Default-initializes objects in the range [first,first+count).
void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last)
Default-initializes objects in the range [first,last).
_ForwardIterator uninitialized_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result)
Copies the range [first,last) into result.
void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last)
Value-initializes objects in the range [first,last).
pair< _InputIterator, _ForwardIterator > uninitialized_move_n(_InputIterator __first, _Size __count, _ForwardIterator __result)
Move-construct from the range [first,first+count) into result.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:137
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition move.h:51
ISO C++ entities toplevel namespace is std.