1 // nonstandard construct and destroy functions -*- C++ -*-
2 
3 // Copyright (C) 2001-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 /*
26  *
27  * Copyright (c) 1994
28  * Hewlett-Packard Company
29  *
30  * Permission to use, copy, modify, distribute and sell this software
31  * and its documentation for any purpose is hereby granted without fee,
32  * provided that the above copyright notice appear in all copies and
33  * that both that copyright notice and this permission notice appear
34  * in supporting documentation.  Hewlett-Packard Company makes no
35  * representations about the suitability of this software for any
36  * purpose.  It is provided "as is" without express or implied warranty.
37  *
38  *
39  * Copyright (c) 1996,1997
40  * Silicon Graphics Computer Systems, Inc.
41  *
42  * Permission to use, copy, modify, distribute and sell this software
43  * and its documentation for any purpose is hereby granted without fee,
44  * provided that the above copyright notice appear in all copies and
45  * that both that copyright notice and this permission notice appear
46  * in supporting documentation.  Silicon Graphics makes no
47  * representations about the suitability of this software for any
48  * purpose.  It is provided "as is" without express or implied warranty.
49  */
50 
51 /** @file bits/stl_construct.h
52  *  This is an internal header file, included by other library headers.
53  *  Do not attempt to use it directly. @headername{memory}
54  */
55 
56 #ifndef _STL_CONSTRUCT_H
57 #define _STL_CONSTRUCT_H 1
58 
59 #include <new>
60 #include <bits/move.h>
61 #include <bits/stl_iterator_base_types.h> // for iterator_traits
62 #include <bits/stl_iterator_base_funcs.h> // for advance
63 
64 /* This file provides the C++17 functions std::destroy_at, std::destroy, and
65  * std::destroy_n, and the C++20 function std::construct_at.
66  * It also provides std::_Construct, std::_Destroy,and std::_Destroy_n functions
67  * which are defined in all standard modes and so can be used in C++98-14 code.
68  * The _Destroy functions will dispatch to destroy_at during constant
69  * evaluation, because calls to that function are intercepted by the compiler
70  * to allow use in constant expressions.
71  */
72 
_GLIBCXX_VISIBILITY(default)73 namespace std _GLIBCXX_VISIBILITY(default)
74 {
75 _GLIBCXX_BEGIN_NAMESPACE_VERSION
76 
77 #if __cplusplus >= 201703L
78   template <typename _Tp>
79     _GLIBCXX20_CONSTEXPR inline void
80     destroy_at(_Tp* __location)
81     {
82       if constexpr (__cplusplus > 201703L && is_array_v<_Tp>)
83 	{
84 	  for (auto& __x : *__location)
85 	    std::destroy_at(std::__addressof(__x));
86 	}
87       else
88 	__location->~_Tp();
89     }
90 
91 #if __cplusplus >= 202002L
92   template<typename _Tp, typename... _Args>
93     constexpr auto
94     construct_at(_Tp* __location, _Args&&... __args)
95     noexcept(noexcept(::new((void*)0) _Tp(std::declval<_Args>()...)))
96     -> decltype(::new((void*)0) _Tp(std::declval<_Args>()...))
97     { return ::new((void*)__location) _Tp(std::forward<_Args>(__args)...); }
98 #endif // C++20
99 #endif// C++17
100 
101   /**
102    * Constructs an object in existing memory by invoking an allocated
103    * object's constructor with an initializer.
104    */
105 #if __cplusplus >= 201103L
106   template<typename _Tp, typename... _Args>
107     _GLIBCXX20_CONSTEXPR
108     inline void
109     _Construct(_Tp* __p, _Args&&... __args)
110     {
111 #if __cplusplus >= 202002L
112       if (std::__is_constant_evaluated())
113 	{
114 	  // Allow std::_Construct to be used in constant expressions.
115 	  std::construct_at(__p, std::forward<_Args>(__args)...);
116 	  return;
117 	}
118 #endif
119       ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
120     }
121 #else
122   template<typename _T1, typename _T2>
123     inline void
124     _Construct(_T1* __p, const _T2& __value)
125     {
126       // _GLIBCXX_RESOLVE_LIB_DEFECTS
127       // 402. wrong new expression in [some_]allocator::construct
128       ::new(static_cast<void*>(__p)) _T1(__value);
129     }
130 #endif
131 
132   template<typename _T1>
133     inline void
134     _Construct_novalue(_T1* __p)
135     { ::new((void*)__p) _T1; }
136 
137   template<typename _ForwardIterator>
138     _GLIBCXX20_CONSTEXPR void
139     _Destroy(_ForwardIterator __first, _ForwardIterator __last);
140 
141   /**
142    * Destroy the object pointed to by a pointer type.
143    */
144   template<typename _Tp>
145     _GLIBCXX14_CONSTEXPR inline void
146     _Destroy(_Tp* __pointer)
147     {
148 #if __cplusplus > 201703L
149       std::destroy_at(__pointer);
150 #else
151       __pointer->~_Tp();
152 #endif
153     }
154 
155   template<bool>
156     struct _Destroy_aux
157     {
158       template<typename _ForwardIterator>
159 	static _GLIBCXX20_CONSTEXPR void
160 	__destroy(_ForwardIterator __first, _ForwardIterator __last)
161 	{
162 	  for (; __first != __last; ++__first)
163 	    std::_Destroy(std::__addressof(*__first));
164 	}
165     };
166 
167   template<>
168     struct _Destroy_aux<true>
169     {
170       template<typename _ForwardIterator>
171         static void
172         __destroy(_ForwardIterator, _ForwardIterator) { }
173     };
174 
175   /**
176    * Destroy a range of objects.  If the value_type of the object has
177    * a trivial destructor, the compiler should optimize all of this
178    * away, otherwise the objects' destructors must be invoked.
179    */
180   template<typename _ForwardIterator>
181     _GLIBCXX20_CONSTEXPR inline void
182     _Destroy(_ForwardIterator __first, _ForwardIterator __last)
183     {
184       typedef typename iterator_traits<_ForwardIterator>::value_type
185                        _Value_type;
186 #if __cplusplus >= 201103L
187       // A deleted destructor is trivial, this ensures we reject such types:
188       static_assert(is_destructible<_Value_type>::value,
189 		    "value type is destructible");
190 #endif
191 #if __cplusplus >= 202002L
192       if (std::__is_constant_evaluated())
193 	return _Destroy_aux<false>::__destroy(__first, __last);
194 #endif
195       std::_Destroy_aux<__has_trivial_destructor(_Value_type)>::
196 	__destroy(__first, __last);
197     }
198 
199   template<bool>
200     struct _Destroy_n_aux
201     {
202       template<typename _ForwardIterator, typename _Size>
203 	static _GLIBCXX20_CONSTEXPR _ForwardIterator
204 	__destroy_n(_ForwardIterator __first, _Size __count)
205 	{
206 	  for (; __count > 0; (void)++__first, --__count)
207 	    std::_Destroy(std::__addressof(*__first));
208 	  return __first;
209 	}
210     };
211 
212   template<>
213     struct _Destroy_n_aux<true>
214     {
215       template<typename _ForwardIterator, typename _Size>
216         static _ForwardIterator
217         __destroy_n(_ForwardIterator __first, _Size __count)
218 	{
219 	  std::advance(__first, __count);
220 	  return __first;
221 	}
222     };
223 
224   /**
225    * Destroy a range of objects.  If the value_type of the object has
226    * a trivial destructor, the compiler should optimize all of this
227    * away, otherwise the objects' destructors must be invoked.
228    */
229   template<typename _ForwardIterator, typename _Size>
230     _GLIBCXX20_CONSTEXPR inline _ForwardIterator
231     _Destroy_n(_ForwardIterator __first, _Size __count)
232     {
233       typedef typename iterator_traits<_ForwardIterator>::value_type
234                        _Value_type;
235 #if __cplusplus >= 201103L
236       // A deleted destructor is trivial, this ensures we reject such types:
237       static_assert(is_destructible<_Value_type>::value,
238 		    "value type is destructible");
239 #endif
240 #if __cplusplus >= 202002L
241       if (std::__is_constant_evaluated())
242 	return _Destroy_n_aux<false>::__destroy_n(__first, __count);
243 #endif
244       return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>::
245 	__destroy_n(__first, __count);
246     }
247 
248 #if __cplusplus >= 201703L
249   template <typename _ForwardIterator>
250     _GLIBCXX20_CONSTEXPR inline void
251     destroy(_ForwardIterator __first, _ForwardIterator __last)
252     {
253       std::_Destroy(__first, __last);
254     }
255 
256   template <typename _ForwardIterator, typename _Size>
257     _GLIBCXX20_CONSTEXPR inline _ForwardIterator
258     destroy_n(_ForwardIterator __first, _Size __count)
259     {
260       return std::_Destroy_n(__first, __count);
261     }
262 #endif // C++17
263 
264 _GLIBCXX_END_NAMESPACE_VERSION
265 } // namespace std
266 
267 #endif /* _STL_CONSTRUCT_H */
268