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