Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===----------------------------------------------------------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H |
10 | #define _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H |
11 | |
12 | #include <__config> |
13 | #include <__memory/construct_at.h> |
14 | #include <__memory/uses_allocator.h> |
15 | #include <__tuple/tuple_like_no_subrange.h> |
16 | #include <__type_traits/enable_if.h> |
17 | #include <__type_traits/remove_cv.h> |
18 | #include <__utility/declval.h> |
19 | #include <__utility/pair.h> |
20 | #include <tuple> |
21 | |
22 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
23 | # pragma GCC system_header |
24 | #endif |
25 | |
26 | _LIBCPP_PUSH_MACROS |
27 | #include <__undef_macros> |
28 | |
29 | _LIBCPP_BEGIN_NAMESPACE_STD |
30 | |
31 | #if _LIBCPP_STD_VER >= 17 |
32 | |
33 | template <class _Tp> |
34 | inline constexpr bool __is_cv_std_pair = __is_pair_v<remove_cv_t<_Tp>>; |
35 | |
36 | template <class _Tp, class = void> |
37 | struct __uses_allocator_construction_args; |
38 | |
39 | namespace __uses_allocator_detail { |
40 | |
41 | template <class _Ap, class _Bp> |
42 | void __fun(const pair<_Ap, _Bp>&); |
43 | |
44 | template <class _Tp> |
45 | decltype(__uses_allocator_detail::__fun(std::declval<_Tp>()), true_type()) __convertible_to_const_pair_ref_impl(int); |
46 | |
47 | template <class> |
48 | false_type __convertible_to_const_pair_ref_impl(...); |
49 | |
50 | template <class _Tp> |
51 | inline constexpr bool __convertible_to_const_pair_ref = |
52 | decltype(__uses_allocator_detail::__convertible_to_const_pair_ref_impl<_Tp>(0))::value; |
53 | |
54 | # if _LIBCPP_STD_VER >= 23 |
55 | template <class _Tp, class _Up> |
56 | inline constexpr bool __uses_allocator_constraints = |
57 | __is_cv_std_pair<_Tp> && !__pair_like_no_subrange<_Up> && !__convertible_to_const_pair_ref<_Up>; |
58 | # else |
59 | template <class _Tp, class _Up> |
60 | inline constexpr bool __uses_allocator_constraints = __is_cv_std_pair<_Tp> && !__convertible_to_const_pair_ref<_Up>; |
61 | # endif |
62 | |
63 | } // namespace __uses_allocator_detail |
64 | |
65 | template <class _Type, class _Alloc, class... _Args> |
66 | _LIBCPP_HIDE_FROM_ABI constexpr _Type __make_obj_using_allocator(const _Alloc& __alloc, _Args&&... __args); |
67 | |
68 | template <class _Pair> |
69 | struct __uses_allocator_construction_args<_Pair, __enable_if_t<__is_cv_std_pair<_Pair>>> { |
70 | template <class _Alloc, class _Tuple1, class _Tuple2> |
71 | static _LIBCPP_HIDE_FROM_ABI constexpr auto |
72 | __apply(const _Alloc& __alloc, piecewise_construct_t, _Tuple1&& __x, _Tuple2&& __y) noexcept { |
73 | return std::make_tuple( |
74 | piecewise_construct, |
75 | std::apply( |
76 | [&__alloc](auto&&... __args1) { |
77 | return __uses_allocator_construction_args<typename _Pair::first_type>::__apply( |
78 | __alloc, std::forward<decltype(__args1)>(__args1)...); |
79 | }, |
80 | std::forward<_Tuple1>(__x)), |
81 | std::apply( |
82 | [&__alloc](auto&&... __args2) { |
83 | return __uses_allocator_construction_args<typename _Pair::second_type>::__apply( |
84 | __alloc, std::forward<decltype(__args2)>(__args2)...); |
85 | }, |
86 | std::forward<_Tuple2>(__y))); |
87 | } |
88 | |
89 | template <class _Alloc> |
90 | static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc) noexcept { |
91 | return __uses_allocator_construction_args<_Pair>::__apply(__alloc, piecewise_construct, tuple<>{}, tuple<>{}); |
92 | } |
93 | |
94 | template <class _Alloc, class _Up, class _Vp> |
95 | static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _Up&& __u, _Vp&& __v) noexcept { |
96 | return __uses_allocator_construction_args<_Pair>::__apply( |
97 | __alloc, |
98 | piecewise_construct, |
99 | std::forward_as_tuple(std::forward<_Up>(__u)), |
100 | std::forward_as_tuple(std::forward<_Vp>(__v))); |
101 | } |
102 | |
103 | # if _LIBCPP_STD_VER >= 23 |
104 | template <class _Alloc, class _Up, class _Vp> |
105 | static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, pair<_Up, _Vp>& __pair) noexcept { |
106 | return __uses_allocator_construction_args<_Pair>::__apply( |
107 | __alloc, piecewise_construct, std::forward_as_tuple(__pair.first), std::forward_as_tuple(__pair.second)); |
108 | } |
109 | # endif |
110 | |
111 | template <class _Alloc, class _Up, class _Vp> |
112 | static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, const pair<_Up, _Vp>& __pair) noexcept { |
113 | return __uses_allocator_construction_args<_Pair>::__apply( |
114 | __alloc, piecewise_construct, std::forward_as_tuple(__pair.first), std::forward_as_tuple(__pair.second)); |
115 | } |
116 | |
117 | template <class _Alloc, class _Up, class _Vp> |
118 | static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, pair<_Up, _Vp>&& __pair) noexcept { |
119 | return __uses_allocator_construction_args<_Pair>::__apply( |
120 | __alloc, |
121 | piecewise_construct, |
122 | std::forward_as_tuple(std::get<0>(std::move(__pair))), |
123 | std::forward_as_tuple(std::get<1>(std::move(__pair)))); |
124 | } |
125 | |
126 | # if _LIBCPP_STD_VER >= 23 |
127 | template <class _Alloc, class _Up, class _Vp> |
128 | static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, const pair<_Up, _Vp>&& __pair) noexcept { |
129 | return __uses_allocator_construction_args<_Pair>::__apply( |
130 | __alloc, |
131 | piecewise_construct, |
132 | std::forward_as_tuple(std::get<0>(std::move(__pair))), |
133 | std::forward_as_tuple(std::get<1>(std::move(__pair)))); |
134 | } |
135 | |
136 | template < class _Alloc, __pair_like_no_subrange _PairLike> |
137 | static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _PairLike&& __p) noexcept { |
138 | return __uses_allocator_construction_args<_Pair>::__apply( |
139 | __alloc, |
140 | piecewise_construct, |
141 | std::forward_as_tuple(std::get<0>(std::forward<_PairLike>(__p))), |
142 | std::forward_as_tuple(std::get<1>(std::forward<_PairLike>(__p)))); |
143 | } |
144 | # endif |
145 | |
146 | template <class _Alloc, |
147 | class _Type, |
148 | __enable_if_t<__uses_allocator_detail::__uses_allocator_constraints<_Pair, _Type>, int> = 0> |
149 | static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _Type&& __value) noexcept { |
150 | struct __pair_constructor { |
151 | using _PairMutable = remove_cv_t<_Pair>; |
152 | |
153 | _LIBCPP_HIDDEN constexpr auto __do_construct(const _PairMutable& __pair) const { |
154 | return std::__make_obj_using_allocator<_PairMutable>(__alloc_, __pair); |
155 | } |
156 | |
157 | _LIBCPP_HIDDEN constexpr auto __do_construct(_PairMutable&& __pair) const { |
158 | return std::__make_obj_using_allocator<_PairMutable>(__alloc_, std::move(__pair)); |
159 | } |
160 | |
161 | const _Alloc& __alloc_; |
162 | _Type& __value_; |
163 | |
164 | _LIBCPP_HIDDEN constexpr operator _PairMutable() const { return __do_construct(std::forward<_Type>(__value_)); } |
165 | }; |
166 | |
167 | return std::make_tuple(__pair_constructor{__alloc, __value}); |
168 | } |
169 | }; |
170 | |
171 | template <class _Type> |
172 | struct __uses_allocator_construction_args<_Type, __enable_if_t<!__is_cv_std_pair<_Type>>> { |
173 | template <class _Alloc, class... _Args> |
174 | static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _Args&&... __args) noexcept { |
175 | if constexpr (!uses_allocator_v<remove_cv_t<_Type>, _Alloc> && is_constructible_v<_Type, _Args...>) { |
176 | return std::forward_as_tuple(std::forward<_Args>(__args)...); |
177 | } else if constexpr (uses_allocator_v<remove_cv_t<_Type>, _Alloc> && |
178 | is_constructible_v<_Type, allocator_arg_t, const _Alloc&, _Args...>) { |
179 | return tuple<allocator_arg_t, const _Alloc&, _Args&&...>(allocator_arg, __alloc, std::forward<_Args>(__args)...); |
180 | } else if constexpr (uses_allocator_v<remove_cv_t<_Type>, _Alloc> && |
181 | is_constructible_v<_Type, _Args..., const _Alloc&>) { |
182 | return std::forward_as_tuple(std::forward<_Args>(__args)..., __alloc); |
183 | } else { |
184 | static_assert( |
185 | sizeof(_Type) + 1 == 0, "If uses_allocator_v<Type> is true, the type has to be allocator-constructible"); |
186 | } |
187 | } |
188 | }; |
189 | |
190 | template <class _Type, class _Alloc, class... _Args> |
191 | _LIBCPP_HIDE_FROM_ABI constexpr _Type __make_obj_using_allocator(const _Alloc& __alloc, _Args&&... __args) { |
192 | return std::make_from_tuple<_Type>( |
193 | __uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...)); |
194 | } |
195 | |
196 | template <class _Type, class _Alloc, class... _Args> |
197 | _LIBCPP_HIDE_FROM_ABI constexpr _Type* |
198 | __uninitialized_construct_using_allocator(_Type* __ptr, const _Alloc& __alloc, _Args&&... __args) { |
199 | return std::apply( |
200 | [&__ptr](auto&&... __xs) { return std::__construct_at(__ptr, std::forward<decltype(__xs)>(__xs)...); }, |
201 | __uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...)); |
202 | } |
203 | |
204 | #endif // _LIBCPP_STD_VER >= 17 |
205 | |
206 | #if _LIBCPP_STD_VER >= 20 |
207 | |
208 | template <class _Type, class _Alloc, class... _Args> |
209 | _LIBCPP_HIDE_FROM_ABI constexpr auto uses_allocator_construction_args(const _Alloc& __alloc, _Args&&... __args) noexcept |
210 | -> decltype(__uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...)) { |
211 | return /*--*/ __uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...); |
212 | } |
213 | |
214 | template <class _Type, class _Alloc, class... _Args> |
215 | _LIBCPP_HIDE_FROM_ABI constexpr auto make_obj_using_allocator(const _Alloc& __alloc, _Args&&... __args) |
216 | -> decltype(std::__make_obj_using_allocator<_Type>(__alloc, std::forward<_Args>(__args)...)) { |
217 | return /*--*/ std::__make_obj_using_allocator<_Type>(__alloc, std::forward<_Args>(__args)...); |
218 | } |
219 | |
220 | template <class _Type, class _Alloc, class... _Args> |
221 | _LIBCPP_HIDE_FROM_ABI constexpr auto |
222 | uninitialized_construct_using_allocator(_Type* __ptr, const _Alloc& __alloc, _Args&&... __args) |
223 | -> decltype(std::__uninitialized_construct_using_allocator(__ptr, __alloc, std::forward<_Args>(__args)...)) { |
224 | return /*--*/ std::__uninitialized_construct_using_allocator(__ptr, __alloc, std::forward<_Args>(__args)...); |
225 | } |
226 | |
227 | #endif // _LIBCPP_STD_VER >= 20 |
228 | |
229 | _LIBCPP_END_NAMESPACE_STD |
230 | |
231 | _LIBCPP_POP_MACROS |
232 | |
233 | #endif // _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H |
234 |
Warning: This file is not a C or C++ file. It does not have highlighting.