libstdc++
ranges_uninitialized.h
Go to the documentation of this file.
1// Raw memory manipulators -*- C++ -*-
2
3// Copyright (C) 2020-2025 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_trivially_default_constructible_v<_ValueType>
206 && is_trivially_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_trivially_default_constructible_v<_ValueType>
239 && is_trivially_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_trivially_constructible_v<_OutType, iter_reference_t<_Iter>>
272 && is_trivially_default_constructible_v<_OutType>
273 && is_trivially_assignable_v<_OutType&,
274 iter_reference_t<_Iter>>)
275 {
276 auto __d1 = __ilast - __ifirst;
277 auto __d2 = __olast - __ofirst;
278 return ranges::copy_n(std::move(__ifirst), std::min(__d1, __d2),
279 __ofirst);
280 }
281 else
282 {
283 auto __guard = __detail::_DestroyGuard(__ofirst);
284 for (; __ifirst != __ilast && __ofirst != __olast;
285 ++__ofirst, (void)++__ifirst)
286 ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst);
287 __guard.release();
288 return {std::move(__ifirst), __ofirst};
289 }
290 }
291
292 template<input_range _IRange, __detail::__nothrow_forward_range _ORange>
293 requires constructible_from<range_value_t<_ORange>,
294 range_reference_t<_IRange>>
295 uninitialized_copy_result<borrowed_iterator_t<_IRange>,
296 borrowed_iterator_t<_ORange>>
297 operator()(_IRange&& __inr, _ORange&& __outr) const
298 {
299 return (*this)(ranges::begin(__inr), ranges::end(__inr),
300 ranges::begin(__outr), ranges::end(__outr));
301 }
302 };
303
304 inline constexpr __uninitialized_copy_fn uninitialized_copy{};
305
306 template<typename _Iter, typename _Out>
307 using uninitialized_copy_n_result = in_out_result<_Iter, _Out>;
308
309 struct __uninitialized_copy_n_fn
310 {
311 template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out,
312 __detail::__nothrow_sentinel<_Out> _Sent>
313 requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>>
314 uninitialized_copy_n_result<_Iter, _Out>
315 operator()(_Iter __ifirst, iter_difference_t<_Iter> __n,
316 _Out __ofirst, _Sent __olast) const
317 {
318 using _OutType = remove_reference_t<iter_reference_t<_Out>>;
319 if constexpr (sized_sentinel_for<_Sent, _Out>
320 && is_trivially_constructible_v<_OutType, iter_reference_t<_Iter>>
321 && is_trivially_default_constructible_v<_OutType>
322 && is_trivially_assignable_v<_OutType&,
323 iter_reference_t<_Iter>>)
324 {
325 auto __d = __olast - __ofirst;
326 return ranges::copy_n(std::move(__ifirst), std::min(__n, __d),
327 __ofirst);
328 }
329 else
330 {
331 auto __guard = __detail::_DestroyGuard(__ofirst);
332 for (; __n > 0 && __ofirst != __olast;
333 ++__ofirst, (void)++__ifirst, (void)--__n)
334 ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst);
335 __guard.release();
336 return {std::move(__ifirst), __ofirst};
337 }
338 }
339 };
340
341 inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{};
342
343 template<typename _Iter, typename _Out>
344 using uninitialized_move_result = in_out_result<_Iter, _Out>;
345
346 struct __uninitialized_move_fn
347 {
348 template<input_iterator _Iter, sentinel_for<_Iter> _ISent,
349 __detail::__nothrow_forward_iterator _Out,
350 __detail::__nothrow_sentinel<_Out> _OSent>
351 requires constructible_from<iter_value_t<_Out>,
352 iter_rvalue_reference_t<_Iter>>
353 uninitialized_move_result<_Iter, _Out>
354 operator()(_Iter __ifirst, _ISent __ilast,
355 _Out __ofirst, _OSent __olast) const
356 {
357 using _OutType = remove_reference_t<iter_reference_t<_Out>>;
358 if constexpr (sized_sentinel_for<_ISent, _Iter>
359 && sized_sentinel_for<_OSent, _Out>
360 && is_trivially_constructible_v<_OutType, iter_rvalue_reference_t<_Iter>>
361 && is_trivially_default_constructible_v<_OutType>
362 && is_trivially_assignable_v<_OutType&,
363 iter_rvalue_reference_t<_Iter>>)
364 {
365 auto __d1 = __ilast - __ifirst;
366 auto __d2 = __olast - __ofirst;
367 auto [__in, __out]
368 = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)),
369 std::min(__d1, __d2), __ofirst);
370 return {std::move(__in).base(), __out};
371 }
372 else
373 {
374 auto __guard = __detail::_DestroyGuard(__ofirst);
375 for (; __ifirst != __ilast && __ofirst != __olast;
376 ++__ofirst, (void)++__ifirst)
377 ::new (__detail::__voidify(*__ofirst))
378 _OutType(ranges::iter_move(__ifirst));
379 __guard.release();
380 return {std::move(__ifirst), __ofirst};
381 }
382 }
383
384 template<input_range _IRange, __detail::__nothrow_forward_range _ORange>
385 requires constructible_from<range_value_t<_ORange>,
386 range_rvalue_reference_t<_IRange>>
387 uninitialized_move_result<borrowed_iterator_t<_IRange>,
388 borrowed_iterator_t<_ORange>>
389 operator()(_IRange&& __inr, _ORange&& __outr) const
390 {
391 return (*this)(ranges::begin(__inr), ranges::end(__inr),
392 ranges::begin(__outr), ranges::end(__outr));
393 }
394 };
395
396 inline constexpr __uninitialized_move_fn uninitialized_move{};
397
398 template<typename _Iter, typename _Out>
399 using uninitialized_move_n_result = in_out_result<_Iter, _Out>;
400
401 struct __uninitialized_move_n_fn
402 {
403 template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out,
404 __detail::__nothrow_sentinel<_Out> _Sent>
405 requires constructible_from<iter_value_t<_Out>,
406 iter_rvalue_reference_t<_Iter>>
407 uninitialized_move_n_result<_Iter, _Out>
408 operator()(_Iter __ifirst, iter_difference_t<_Iter> __n,
409 _Out __ofirst, _Sent __olast) const
410 {
411 using _OutType = remove_reference_t<iter_reference_t<_Out>>;
412 if constexpr (sized_sentinel_for<_Sent, _Out>
413 && is_trivially_constructible_v<_OutType, iter_rvalue_reference_t<_Iter>>
414 && is_trivially_default_constructible_v<_OutType>
415 && is_trivially_assignable_v<_OutType&,
416 iter_rvalue_reference_t<_Iter>>)
417 {
418 auto __d = __olast - __ofirst;
419 auto [__in, __out]
420 = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)),
421 std::min(__n, __d), __ofirst);
422 return {std::move(__in).base(), __out};
423 }
424 else
425 {
426 auto __guard = __detail::_DestroyGuard(__ofirst);
427 for (; __n > 0 && __ofirst != __olast;
428 ++__ofirst, (void)++__ifirst, (void)--__n)
429 ::new (__detail::__voidify(*__ofirst))
430 _OutType(ranges::iter_move(__ifirst));
431 __guard.release();
432 return {std::move(__ifirst), __ofirst};
433 }
434 }
435 };
436
437 inline constexpr __uninitialized_move_n_fn uninitialized_move_n{};
438
439 struct __uninitialized_fill_fn
440 {
441 template<__detail::__nothrow_forward_iterator _Iter,
442 __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp>
443 requires constructible_from<iter_value_t<_Iter>, const _Tp&>
444 _Iter
445 operator()(_Iter __first, _Sent __last, const _Tp& __x) const
446 {
447 using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
448 if constexpr (is_trivially_constructible_v<_ValueType, const _Tp&>
449 && is_trivially_assignable_v<_ValueType&, const _Tp&>)
450 return ranges::fill(__first, __last, __x);
451 else
452 {
453 auto __guard = __detail::_DestroyGuard(__first);
454 for (; __first != __last; ++__first)
455 ::new (__detail::__voidify(*__first)) _ValueType(__x);
456 __guard.release();
457 return __first;
458 }
459 }
460
461 template<__detail::__nothrow_forward_range _Range, typename _Tp>
462 requires constructible_from<range_value_t<_Range>, const _Tp&>
463 borrowed_iterator_t<_Range>
464 operator()(_Range&& __r, const _Tp& __x) const
465 {
466 return (*this)(ranges::begin(__r), ranges::end(__r), __x);
467 }
468 };
469
470 inline constexpr __uninitialized_fill_fn uninitialized_fill{};
471
472 struct __uninitialized_fill_n_fn
473 {
474 template<__detail::__nothrow_forward_iterator _Iter, typename _Tp>
475 requires constructible_from<iter_value_t<_Iter>, const _Tp&>
476 _Iter
477 operator()(_Iter __first, iter_difference_t<_Iter> __n,
478 const _Tp& __x) const
479 {
480 using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
481 if constexpr (is_trivially_constructible_v<_ValueType, const _Tp&>
482 && is_trivially_assignable_v<_ValueType&, const _Tp&>)
483 return ranges::fill_n(__first, __n, __x);
484 else
485 {
486 auto __guard = __detail::_DestroyGuard(__first);
487 for (; __n > 0; ++__first, (void)--__n)
488 ::new (__detail::__voidify(*__first)) _ValueType(__x);
489 __guard.release();
490 return __first;
491 }
492 }
493 };
494
495 inline constexpr __uninitialized_fill_n_fn uninitialized_fill_n{};
496
497 struct __construct_at_fn
498 {
499 template<typename _Tp, typename... _Args>
500 requires requires {
501 ::new (std::declval<void*>()) _Tp(std::declval<_Args>()...);
502 }
503 constexpr _Tp*
504 operator()(_Tp* __location, _Args&&... __args) const
505 noexcept(noexcept(std::construct_at(__location,
506 std::forward<_Args>(__args)...)))
507 {
508 return std::construct_at(__location,
509 std::forward<_Args>(__args)...);
510 }
511 };
512
513 inline constexpr __construct_at_fn construct_at{};
514
515 struct __destroy_at_fn
516 {
517 template<destructible _Tp>
518 constexpr void
519 operator()(_Tp* __location) const noexcept
520 {
521 if constexpr (is_array_v<_Tp>)
522 ranges::destroy(ranges::begin(*__location), ranges::end(*__location));
523 else
524 __location->~_Tp();
525 }
526 };
527
528 inline constexpr __destroy_at_fn destroy_at{};
529
530 template<__detail::__nothrow_input_iterator _Iter,
531 __detail::__nothrow_sentinel<_Iter> _Sent>
532 requires destructible<iter_value_t<_Iter>>
533 constexpr _Iter
534 __destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept
535 {
536 if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
537 return ranges::next(std::move(__first), __last);
538 else
539 {
540 for (; __first != __last; ++__first)
541 ranges::destroy_at(std::__addressof(*__first));
542 return __first;
543 }
544 }
545
546 template<__detail::__nothrow_input_range _Range>
547 requires destructible<range_value_t<_Range>>
548 constexpr borrowed_iterator_t<_Range>
549 __destroy_fn::operator()(_Range&& __r) const noexcept
550 {
551 return (*this)(ranges::begin(__r), ranges::end(__r));
552 }
553
554 struct __destroy_n_fn
555 {
556 template<__detail::__nothrow_input_iterator _Iter>
557 requires destructible<iter_value_t<_Iter>>
558 constexpr _Iter
559 operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept
560 {
561 if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
562 return ranges::next(std::move(__first), __n);
563 else
564 {
565 for (; __n > 0; ++__first, (void)--__n)
566 ranges::destroy_at(std::__addressof(*__first));
567 return __first;
568 }
569 }
570 };
571
572 inline constexpr __destroy_n_fn destroy_n{};
573}
574_GLIBCXX_END_NAMESPACE_VERSION
575} // namespace std
576#endif // concepts
577#endif // C++20
578#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.
auto declval() noexcept -> decltype(__declval< _Tp >(0))
Definition type_traits:2609
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:138
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition move.h:52
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:72
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
ISO C++ entities toplevel namespace is std.