libstdc++
ranges_uninitialized.h
Go to the documentation of this file.
1// Raw memory manipulators -*- C++ -*-
2
3// Copyright (C) 2020-2021 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 __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
_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:104
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:49
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:230
ISO C++ entities toplevel namespace is std.