libstdc++
ranges_uninitialized.h
Go to the documentation of this file.
1 // Raw memory manipulators -*- C++ -*-
2 
3 // Copyright (C) 2020 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
_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_fill_n(_ForwardIterator __first, _Size __n, const _Tp &__x)
Copies the value x into the range [first,first+n).
_ForwardIterator uninitialized_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result)
Copies the range [first,last) into result.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:49
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:101
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:76
_Tp * end(valarray< _Tp > &__va) noexcept
Return an iterator pointing to one past the last element of the valarray.
Definition: valarray:1234
_Tp * begin(valarray< _Tp > &__va) noexcept
Return an iterator pointing to the first element of the valarray.
Definition: valarray:1214
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.