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
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
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