1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP___MEMORY_CONSTRUCT_AT_H
11 #define _LIBCPP___MEMORY_CONSTRUCT_AT_H
12 
13 #include <__assert>
14 #include <__config>
15 #include <__iterator/access.h>
16 #include <__memory/addressof.h>
17 #include <__memory/voidify.h>
18 #include <__utility/forward.h>
19 #include <__utility/move.h>
20 #include <type_traits>
21 
22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23 #  pragma GCC system_header
24 #endif
25 
26 _LIBCPP_BEGIN_NAMESPACE_STD
27 
28 // construct_at
29 
30 #if _LIBCPP_STD_VER > 17
31 
32 template <class _Tp, class... _Args, class = decltype(::new(declval<void*>()) _Tp(declval<_Args>()...))>
33 _LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) {
34   _LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at");
35   return ::new (_VSTD::__voidify(*__location)) _Tp(_VSTD::forward<_Args>(__args)...);
36 }
37 
38 #endif
39 
40 template <class _Tp, class... _Args, class = decltype(::new(declval<void*>()) _Tp(declval<_Args>()...))>
41 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __construct_at(_Tp* __location, _Args&&... __args) {
42 #if _LIBCPP_STD_VER > 17
43   return std::construct_at(__location, std::forward<_Args>(__args)...);
44 #else
45   return ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...);
46 #endif
47 }
48 
49 // destroy_at
50 
51 // The internal functions are available regardless of the language version (with the exception of the `__destroy_at`
52 // taking an array).
53 
54 template <class _ForwardIterator>
55 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
56 _ForwardIterator __destroy(_ForwardIterator, _ForwardIterator);
57 
58 template <class _Tp, typename enable_if<!is_array<_Tp>::value, int>::type = 0>
59 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
60 void __destroy_at(_Tp* __loc) {
61     _LIBCPP_ASSERT(__loc != nullptr, "null pointer given to destroy_at");
62     __loc->~_Tp();
63 }
64 
65 #if _LIBCPP_STD_VER > 17
66 template <class _Tp, typename enable_if<is_array<_Tp>::value, int>::type = 0>
67 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
68 void __destroy_at(_Tp* __loc) {
69     _LIBCPP_ASSERT(__loc != nullptr, "null pointer given to destroy_at");
70     _VSTD::__destroy(_VSTD::begin(*__loc), _VSTD::end(*__loc));
71 }
72 #endif
73 
74 template <class _ForwardIterator>
75 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
76 _ForwardIterator __destroy(_ForwardIterator __first, _ForwardIterator __last) {
77     for (; __first != __last; ++__first)
78         _VSTD::__destroy_at(_VSTD::addressof(*__first));
79     return __first;
80 }
81 
82 #if _LIBCPP_STD_VER > 14
83 
84 template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0>
85 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
86 void destroy_at(_Tp* __loc) {
87     _VSTD::__destroy_at(__loc);
88 }
89 
90 #if _LIBCPP_STD_VER > 17
91 template <class _Tp, enable_if_t<is_array_v<_Tp>, int> = 0>
92 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
93 void destroy_at(_Tp* __loc) {
94   _VSTD::__destroy_at(__loc);
95 }
96 #endif
97 
98 template <class _ForwardIterator>
99 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
100 void destroy(_ForwardIterator __first, _ForwardIterator __last) {
101   (void)_VSTD::__destroy(_VSTD::move(__first), _VSTD::move(__last));
102 }
103 
104 template <class _ForwardIterator, class _Size>
105 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
106 _ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) {
107     for (; __n > 0; (void)++__first, --__n)
108         _VSTD::__destroy_at(_VSTD::addressof(*__first));
109     return __first;
110 }
111 
112 #endif // _LIBCPP_STD_VER > 14
113 
114 _LIBCPP_END_NAMESPACE_STD
115 
116 #endif // _LIBCPP___MEMORY_CONSTRUCT_AT_H
117