libstdc++
ranges_uninitialized.h
Go to the documentation of this file.
1 // Raw memory manipulators -*- C++ -*-
2 
3 // Copyright (C) 2020-2023 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
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
pair< _InputIterator, _ForwardIterator > uninitialized_move_n(_InputIterator __first, _Size __count, _ForwardIterator __result)
Move-construct from the range [first,first+count) into result.
_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).
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:51
auto declval() noexcept -> decltype(__declval< _Tp >(0))
Definition: type_traits:2386
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:97
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:70
ISO C++ entities toplevel namespace is std.