stl_construct.h 8.5 KB

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