1 // Raw memory manipulators -*- C++ -*-
2 
3 // Copyright (C) 2020-2022 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 
_GLIBCXX_VISIBILITY(default)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
575