xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/bits/stl_construct.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
14fee23f9Smrg // nonstandard construct and destroy functions -*- C++ -*-
24fee23f9Smrg 
3b1e83836Smrg // Copyright (C) 2001-2022 Free Software Foundation, Inc.
44fee23f9Smrg //
54fee23f9Smrg // This file is part of the GNU ISO C++ Library.  This library is free
64fee23f9Smrg // software; you can redistribute it and/or modify it under the
74fee23f9Smrg // terms of the GNU General Public License as published by the
84fee23f9Smrg // Free Software Foundation; either version 3, or (at your option)
94fee23f9Smrg // any later version.
104fee23f9Smrg 
114fee23f9Smrg // This library is distributed in the hope that it will be useful,
124fee23f9Smrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
134fee23f9Smrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144fee23f9Smrg // GNU General Public License for more details.
154fee23f9Smrg 
164fee23f9Smrg // Under Section 7 of GPL version 3, you are granted additional
174fee23f9Smrg // permissions described in the GCC Runtime Library Exception, version
184fee23f9Smrg // 3.1, as published by the Free Software Foundation.
194fee23f9Smrg 
204fee23f9Smrg // You should have received a copy of the GNU General Public License and
214fee23f9Smrg // a copy of the GCC Runtime Library Exception along with this program;
224fee23f9Smrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
234fee23f9Smrg // <http://www.gnu.org/licenses/>.
244fee23f9Smrg 
254fee23f9Smrg /*
264fee23f9Smrg  *
274fee23f9Smrg  * Copyright (c) 1994
284fee23f9Smrg  * Hewlett-Packard Company
294fee23f9Smrg  *
304fee23f9Smrg  * Permission to use, copy, modify, distribute and sell this software
314fee23f9Smrg  * and its documentation for any purpose is hereby granted without fee,
324fee23f9Smrg  * provided that the above copyright notice appear in all copies and
334fee23f9Smrg  * that both that copyright notice and this permission notice appear
344fee23f9Smrg  * in supporting documentation.  Hewlett-Packard Company makes no
354fee23f9Smrg  * representations about the suitability of this software for any
364fee23f9Smrg  * purpose.  It is provided "as is" without express or implied warranty.
374fee23f9Smrg  *
384fee23f9Smrg  *
394fee23f9Smrg  * Copyright (c) 1996,1997
404fee23f9Smrg  * Silicon Graphics Computer Systems, Inc.
414fee23f9Smrg  *
424fee23f9Smrg  * Permission to use, copy, modify, distribute and sell this software
434fee23f9Smrg  * and its documentation for any purpose is hereby granted without fee,
444fee23f9Smrg  * provided that the above copyright notice appear in all copies and
454fee23f9Smrg  * that both that copyright notice and this permission notice appear
464fee23f9Smrg  * in supporting documentation.  Silicon Graphics makes no
474fee23f9Smrg  * representations about the suitability of this software for any
484fee23f9Smrg  * purpose.  It is provided "as is" without express or implied warranty.
494fee23f9Smrg  */
504fee23f9Smrg 
5148fb7bfaSmrg /** @file bits/stl_construct.h
524fee23f9Smrg  *  This is an internal header file, included by other library headers.
5348fb7bfaSmrg  *  Do not attempt to use it directly. @headername{memory}
544fee23f9Smrg  */
554fee23f9Smrg 
564fee23f9Smrg #ifndef _STL_CONSTRUCT_H
574fee23f9Smrg #define _STL_CONSTRUCT_H 1
584fee23f9Smrg 
594fee23f9Smrg #include <new>
604fee23f9Smrg #include <bits/move.h>
61fb8a8121Smrg #include <bits/stl_iterator_base_types.h> // for iterator_traits
62fb8a8121Smrg #include <bits/stl_iterator_base_funcs.h> // for advance
63fb8a8121Smrg 
64fb8a8121Smrg /* This file provides the C++17 functions std::destroy_at, std::destroy, and
65fb8a8121Smrg  * std::destroy_n, and the C++20 function std::construct_at.
66fb8a8121Smrg  * It also provides std::_Construct, std::_Destroy,and std::_Destroy_n functions
67fb8a8121Smrg  * which are defined in all standard modes and so can be used in C++98-14 code.
68fb8a8121Smrg  * The _Destroy functions will dispatch to destroy_at during constant
69fb8a8121Smrg  * evaluation, because calls to that function are intercepted by the compiler
70fb8a8121Smrg  * to allow use in constant expressions.
71fb8a8121Smrg  */
724fee23f9Smrg 
_GLIBCXX_VISIBILITY(default)7348fb7bfaSmrg namespace std _GLIBCXX_VISIBILITY(default)
7448fb7bfaSmrg {
7548fb7bfaSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
764fee23f9Smrg 
77fb8a8121Smrg #if __cplusplus >= 201703L
78fb8a8121Smrg   template <typename _Tp>
79fb8a8121Smrg     _GLIBCXX20_CONSTEXPR inline void
80fb8a8121Smrg     destroy_at(_Tp* __location)
81fb8a8121Smrg     {
82fb8a8121Smrg       if constexpr (__cplusplus > 201703L && is_array_v<_Tp>)
83fb8a8121Smrg 	{
84fb8a8121Smrg 	  for (auto& __x : *__location)
85fb8a8121Smrg 	    std::destroy_at(std::__addressof(__x));
86fb8a8121Smrg 	}
87fb8a8121Smrg       else
88fb8a8121Smrg 	__location->~_Tp();
89fb8a8121Smrg     }
90fb8a8121Smrg 
91b1e83836Smrg #if __cplusplus >= 202002L
92fb8a8121Smrg   template<typename _Tp, typename... _Args>
93fb8a8121Smrg     constexpr auto
94fb8a8121Smrg     construct_at(_Tp* __location, _Args&&... __args)
95fb8a8121Smrg     noexcept(noexcept(::new((void*)0) _Tp(std::declval<_Args>()...)))
96fb8a8121Smrg     -> decltype(::new((void*)0) _Tp(std::declval<_Args>()...))
97fb8a8121Smrg     { return ::new((void*)__location) _Tp(std::forward<_Args>(__args)...); }
98fb8a8121Smrg #endif // C++20
99fb8a8121Smrg #endif// C++17
100fb8a8121Smrg 
1014fee23f9Smrg   /**
1024fee23f9Smrg    * Constructs an object in existing memory by invoking an allocated
1034fee23f9Smrg    * object's constructor with an initializer.
1044fee23f9Smrg    */
10548fb7bfaSmrg #if __cplusplus >= 201103L
106fb8a8121Smrg   template<typename _Tp, typename... _Args>
107b1e83836Smrg     _GLIBCXX20_CONSTEXPR
10848fb7bfaSmrg     inline void
109fb8a8121Smrg     _Construct(_Tp* __p, _Args&&... __args)
110b1e83836Smrg     {
111b1e83836Smrg #if __cplusplus >= 202002L
112b1e83836Smrg       if (std::__is_constant_evaluated())
113b1e83836Smrg 	{
114b1e83836Smrg 	  // Allow std::_Construct to be used in constant expressions.
115b1e83836Smrg 	  std::construct_at(__p, std::forward<_Args>(__args)...);
116b1e83836Smrg 	  return;
117b1e83836Smrg 	}
118b1e83836Smrg #endif
119b1e83836Smrg       ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
120b1e83836Smrg     }
12148fb7bfaSmrg #else
1224fee23f9Smrg   template<typename _T1, typename _T2>
1234fee23f9Smrg     inline void
1244fee23f9Smrg     _Construct(_T1* __p, const _T2& __value)
1254fee23f9Smrg     {
1264fee23f9Smrg       // _GLIBCXX_RESOLVE_LIB_DEFECTS
1274fee23f9Smrg       // 402. wrong new expression in [some_]allocator::construct
12848fb7bfaSmrg       ::new(static_cast<void*>(__p)) _T1(__value);
1294fee23f9Smrg     }
13048fb7bfaSmrg #endif
1314fee23f9Smrg 
132b17d1066Smrg   template<typename _T1>
133b17d1066Smrg     inline void
134b17d1066Smrg     _Construct_novalue(_T1* __p)
135b1e83836Smrg     { ::new((void*)__p) _T1; }
136b17d1066Smrg 
137fb8a8121Smrg   template<typename _ForwardIterator>
138fb8a8121Smrg     _GLIBCXX20_CONSTEXPR void
139fb8a8121Smrg     _Destroy(_ForwardIterator __first, _ForwardIterator __last);
140fb8a8121Smrg 
1414fee23f9Smrg   /**
1424fee23f9Smrg    * Destroy the object pointed to by a pointer type.
1434fee23f9Smrg    */
1444fee23f9Smrg   template<typename _Tp>
145fb8a8121Smrg     _GLIBCXX14_CONSTEXPR inline void
1464fee23f9Smrg     _Destroy(_Tp* __pointer)
147fb8a8121Smrg     {
148fb8a8121Smrg #if __cplusplus > 201703L
149fb8a8121Smrg       std::destroy_at(__pointer);
150fb8a8121Smrg #else
151fb8a8121Smrg       __pointer->~_Tp();
152fb8a8121Smrg #endif
153fb8a8121Smrg     }
1544fee23f9Smrg 
1554fee23f9Smrg   template<bool>
1564fee23f9Smrg     struct _Destroy_aux
1574fee23f9Smrg     {
1584fee23f9Smrg       template<typename _ForwardIterator>
159fb8a8121Smrg 	static _GLIBCXX20_CONSTEXPR void
1604fee23f9Smrg 	__destroy(_ForwardIterator __first, _ForwardIterator __last)
1614fee23f9Smrg 	{
1624fee23f9Smrg 	  for (; __first != __last; ++__first)
16348fb7bfaSmrg 	    std::_Destroy(std::__addressof(*__first));
1644fee23f9Smrg 	}
1654fee23f9Smrg     };
1664fee23f9Smrg 
1674fee23f9Smrg   template<>
1684fee23f9Smrg     struct _Destroy_aux<true>
1694fee23f9Smrg     {
1704fee23f9Smrg       template<typename _ForwardIterator>
1714fee23f9Smrg         static void
1724fee23f9Smrg         __destroy(_ForwardIterator, _ForwardIterator) { }
1734fee23f9Smrg     };
1744fee23f9Smrg 
1754fee23f9Smrg   /**
1764fee23f9Smrg    * Destroy a range of objects.  If the value_type of the object has
1774fee23f9Smrg    * a trivial destructor, the compiler should optimize all of this
1784fee23f9Smrg    * away, otherwise the objects' destructors must be invoked.
1794fee23f9Smrg    */
1804fee23f9Smrg   template<typename _ForwardIterator>
181fb8a8121Smrg     _GLIBCXX20_CONSTEXPR inline void
1824fee23f9Smrg     _Destroy(_ForwardIterator __first, _ForwardIterator __last)
1834fee23f9Smrg     {
1844fee23f9Smrg       typedef typename iterator_traits<_ForwardIterator>::value_type
1854fee23f9Smrg                        _Value_type;
186b17d1066Smrg #if __cplusplus >= 201103L
187b17d1066Smrg       // A deleted destructor is trivial, this ensures we reject such types:
188b17d1066Smrg       static_assert(is_destructible<_Value_type>::value,
189b17d1066Smrg 		    "value type is destructible");
190b17d1066Smrg #endif
191b1e83836Smrg #if __cplusplus >= 202002L
192b1e83836Smrg       if (std::__is_constant_evaluated())
193*0a307195Smrg 	return std::_Destroy_aux<false>::__destroy(__first, __last);
194fb8a8121Smrg #endif
1954fee23f9Smrg       std::_Destroy_aux<__has_trivial_destructor(_Value_type)>::
1964fee23f9Smrg 	__destroy(__first, __last);
1974fee23f9Smrg     }
1984fee23f9Smrg 
199b17d1066Smrg   template<bool>
200b17d1066Smrg     struct _Destroy_n_aux
201b17d1066Smrg     {
202b17d1066Smrg       template<typename _ForwardIterator, typename _Size>
203fb8a8121Smrg 	static _GLIBCXX20_CONSTEXPR _ForwardIterator
204b17d1066Smrg 	__destroy_n(_ForwardIterator __first, _Size __count)
205b17d1066Smrg 	{
206b17d1066Smrg 	  for (; __count > 0; (void)++__first, --__count)
207b17d1066Smrg 	    std::_Destroy(std::__addressof(*__first));
208b17d1066Smrg 	  return __first;
209b17d1066Smrg 	}
210b17d1066Smrg     };
211b17d1066Smrg 
212b17d1066Smrg   template<>
213b17d1066Smrg     struct _Destroy_n_aux<true>
214b17d1066Smrg     {
215b17d1066Smrg       template<typename _ForwardIterator, typename _Size>
216b17d1066Smrg         static _ForwardIterator
217b17d1066Smrg         __destroy_n(_ForwardIterator __first, _Size __count)
218b17d1066Smrg 	{
219b17d1066Smrg 	  std::advance(__first, __count);
220b17d1066Smrg 	  return __first;
221b17d1066Smrg 	}
222b17d1066Smrg     };
223b17d1066Smrg 
224b17d1066Smrg   /**
225b17d1066Smrg    * Destroy a range of objects.  If the value_type of the object has
226b17d1066Smrg    * a trivial destructor, the compiler should optimize all of this
227b17d1066Smrg    * away, otherwise the objects' destructors must be invoked.
228b17d1066Smrg    */
229b17d1066Smrg   template<typename _ForwardIterator, typename _Size>
230fb8a8121Smrg     _GLIBCXX20_CONSTEXPR inline _ForwardIterator
231b17d1066Smrg     _Destroy_n(_ForwardIterator __first, _Size __count)
232b17d1066Smrg     {
233b17d1066Smrg       typedef typename iterator_traits<_ForwardIterator>::value_type
234b17d1066Smrg                        _Value_type;
235b17d1066Smrg #if __cplusplus >= 201103L
236b17d1066Smrg       // A deleted destructor is trivial, this ensures we reject such types:
237b17d1066Smrg       static_assert(is_destructible<_Value_type>::value,
238b17d1066Smrg 		    "value type is destructible");
239b17d1066Smrg #endif
240b1e83836Smrg #if __cplusplus >= 202002L
241b1e83836Smrg       if (std::__is_constant_evaluated())
242*0a307195Smrg 	return std::_Destroy_n_aux<false>::__destroy_n(__first, __count);
243fb8a8121Smrg #endif
244b17d1066Smrg       return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>::
245b17d1066Smrg 	__destroy_n(__first, __count);
246b17d1066Smrg     }
247b17d1066Smrg 
248fb8a8121Smrg #if __cplusplus >= 201703L
249b17d1066Smrg   template <typename _ForwardIterator>
250fb8a8121Smrg     _GLIBCXX20_CONSTEXPR inline void
251b17d1066Smrg     destroy(_ForwardIterator __first, _ForwardIterator __last)
252b17d1066Smrg     {
253b17d1066Smrg       std::_Destroy(__first, __last);
254b17d1066Smrg     }
255b17d1066Smrg 
256b17d1066Smrg   template <typename _ForwardIterator, typename _Size>
257fb8a8121Smrg     _GLIBCXX20_CONSTEXPR inline _ForwardIterator
258b17d1066Smrg     destroy_n(_ForwardIterator __first, _Size __count)
259b17d1066Smrg     {
260b17d1066Smrg       return std::_Destroy_n(__first, __count);
261b17d1066Smrg     }
262fb8a8121Smrg #endif // C++17
263b17d1066Smrg 
26448fb7bfaSmrg _GLIBCXX_END_NAMESPACE_VERSION
26548fb7bfaSmrg } // namespace std
2664fee23f9Smrg 
2674fee23f9Smrg #endif /* _STL_CONSTRUCT_H */
268