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