1010#define _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H
1111
1212#include < __config>
13+ #include < __cstddef/size_t.h>
14+ #include < __functional/reference_wrapper.h>
1315#include < __memory/construct_at.h>
1416#include < __memory/uses_allocator.h>
1517#include < __tuple/tuple_like_no_subrange.h>
1618#include < __type_traits/enable_if.h>
19+ #include < __type_traits/invoke.h>
20+ #include < __type_traits/is_constructible.h>
1721#include < __type_traits/remove_cv.h>
22+ #include < __type_traits/remove_cvref.h>
1823#include < __utility/declval.h>
24+ #include < __utility/integer_sequence.h>
1925#include < __utility/pair.h>
2026#include < __utility/piecewise_construct.h>
2127#include < tuple>
@@ -29,7 +35,43 @@ _LIBCPP_PUSH_MACROS
2935
3036_LIBCPP_BEGIN_NAMESPACE_STD
3137
32- #if _LIBCPP_STD_VER >= 17
38+ #if !defined(_LIBCPP_CXX03_LANG) && _LIBCPP_STD_VER < 14
39+
40+ template <class _Alloc , class ... _Args, size_t ... _Is>
41+ _LIBCPP_HIDE_FROM_ABI void __transform_tuple_using_allocator_impl (
42+ integral_constant<int , -1 >, const _Alloc&, tuple<_Args...>&&, __index_sequence<_Is...>) {
43+ static_assert (false , " If uses_allocator_v<T, A> is true, T has to be allocator-constructible" );
44+ }
45+
46+ template <class _Alloc , class ... _Args, size_t ... _Is>
47+ _LIBCPP_HIDE_FROM_ABI tuple<_Args&&...> __transform_tuple_using_allocator_impl (
48+ integral_constant<int , 0 >, const _Alloc&, tuple<_Args...>&& __t , __index_sequence<_Is...>) {
49+ return tuple<_Args&&...>(std::move (__t ));
50+ }
51+
52+ template <class _Alloc , class ... _Args, size_t ... _Is>
53+ _LIBCPP_HIDE_FROM_ABI tuple<allocator_arg_t , const _Alloc&, _Args&&...> __transform_tuple_using_allocator_impl (
54+ integral_constant<int , 1 >, const _Alloc& __a, tuple<_Args...>&& __t , __index_sequence<_Is...>) {
55+ return tuple<allocator_arg_t , const _Alloc&, _Args&&...>(allocator_arg, __a, std::get<_Is>(std::move (__t ))...);
56+ }
57+
58+ template <class _Alloc , class ... _Args, size_t ... _Is>
59+ _LIBCPP_HIDE_FROM_ABI tuple<_Args&&..., const _Alloc&> __transform_tuple_using_allocator_impl (
60+ integral_constant<int , 2 >, const _Alloc& __a, tuple<_Args...>&& __t , __index_sequence<_Is...>) {
61+ return tuple<_Args&&..., const _Alloc&>(std::get<_Is>(std::move (__t ))..., __a);
62+ }
63+
64+ template <class _Tp , class _Alloc , class ... _Args>
65+ _LIBCPP_HIDE_FROM_ABI auto __transform_tuple_using_allocator (const _Alloc& __a, tuple<_Args...>&& __t )
66+ -> decltype(std::__transform_tuple_using_allocator_impl(
67+ __uses_alloc_ctor<_Tp, _Alloc, _Args...>{}, __a, std::move(__t ), __make_index_sequence<sizeof...(_Args)>{})) {
68+ return std::__transform_tuple_using_allocator_impl (
69+ __uses_alloc_ctor<_Tp, _Alloc, _Args...>{}, __a, std::move (__t ), __make_index_sequence<sizeof ...(_Args)>{});
70+ }
71+
72+ #endif // !defined(_LIBCPP_CXX03_LANG) && _LIBCPP_STD_VER < 14
73+
74+ #if _LIBCPP_STD_VER >= 14
3375
3476template <class _Tp >
3577inline constexpr bool __is_cv_std_pair = __is_pair_v<remove_cv_t <_Tp>>;
@@ -40,17 +82,13 @@ struct __uses_allocator_construction_args;
4082namespace __uses_allocator_detail {
4183
4284template <class _Ap , class _Bp >
43- void __fun (const pair<_Ap, _Bp>&);
44-
45- template <class _Tp >
46- decltype (__uses_allocator_detail::__fun(std::declval<_Tp>()), true_type()) __convertible_to_const_pair_ref_impl(int );
47-
48- template <class >
49- false_type __convertible_to_const_pair_ref_impl (...);
85+ void __pair_taker (const pair<_Ap, _Bp>&);
5086
87+ template <class , class = void >
88+ inline constexpr bool __convertible_to_const_pair_ref = false ;
5189template <class _Tp >
52- inline constexpr bool __convertible_to_const_pair_ref =
53- decltype (__uses_allocator_detail::__convertible_to_const_pair_ref_impl <_Tp>(0 ))::value ;
90+ inline constexpr bool
91+ __convertible_to_const_pair_ref<_Tp, decltype (__uses_allocator_detail::__pair_taker(std::declval <_Tp>()))> = true ;
5492
5593# if _LIBCPP_STD_VER >= 23
5694template <class _Tp , class _Up >
@@ -61,25 +99,75 @@ template <class _Tp, class _Up>
6199inline constexpr bool __uses_allocator_constraints = __is_cv_std_pair<_Tp> && !__convertible_to_const_pair_ref<_Up>;
62100# endif
63101
102+ # if _LIBCPP_STD_VER < 17
103+ template <class _Tp >
104+ struct __construction_fn {
105+ template <class ... _Args>
106+ static _LIBCPP_HIDE_FROM_ABI constexpr _Tp operator ()(_Args&&... __args) {
107+ static_assert (is_constructible<_Tp, _Args...>::value, " undesired C-style cast used" );
108+ return _Tp (std::forward<_Args&&>(__args)...);
109+ }
110+ };
111+
112+ template <class _Fn , class _Tuple , size_t ... _Ip>
113+ _LIBCPP_HIDE_FROM_ABI constexpr decltype (auto ) __apply_impl(_Fn&& __fn, _Tuple&& __t , index_sequence<_Ip...>) {
114+ return std::__invoke (std::forward<_Fn>(__fn), std::get<_Ip>(std::forward<_Tuple>(__t ))...);
115+ }
116+ # endif // _LIBCPP_STD_VER < 17
117+
118+ template <class _Fn , class _Tuple >
119+ _LIBCPP_HIDE_FROM_ABI constexpr decltype (auto ) __apply(_Fn&& __fn, _Tuple&& __t ) {
120+ # if _LIBCPP_STD_VER >= 17
121+ return std::apply (std::forward<_Fn>(__fn), std::forward<_Tuple>(__t ));
122+ # else
123+ return __uses_allocator_detail::__apply_impl (
124+ std::forward<_Fn>(__fn),
125+ std::forward<_Tuple>(__t ),
126+ std::make_index_sequence<tuple_size<__remove_cvref_t <_Tuple>>::value>{});
127+ # endif
128+ }
129+
130+ template <class _Tp , class _Tuple >
131+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple (_Tuple&& __t ) {
132+ # if _LIBCPP_STD_VER >= 17
133+ return std::make_from_tuple<_Tp>(std::forward<_Tuple>(__t ));
134+ # else
135+ return __uses_allocator_detail::__apply_impl (
136+ __construction_fn<_Tp>{},
137+ std::forward<_Tuple>(__t ),
138+ std::make_index_sequence<tuple_size<__remove_cvref_t <_Tuple>>::value>{});
139+ # endif
140+ }
141+
142+ template <class _Tp , class ... _Args, class = decltype (::new (std::declval<void *>()) _Tp(std::declval<_Args>()...))>
143+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* __construct_at_nocv (_Tp* __location, _Args&&... __args) {
144+ return std::__construct_at (const_cast <remove_cv_t <_Tp>*>(__location), std::forward<_Args>(__args)...);
145+ }
146+
64147} // namespace __uses_allocator_detail
65148
66149template <class _Type , class _Alloc , class ... _Args>
67- _LIBCPP_HIDE_FROM_ABI constexpr _Type __make_obj_using_allocator (const _Alloc& __alloc, _Args&&... __args);
150+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _Type
151+ __make_obj_using_allocator (const _Alloc& __alloc, _Args&&... __args);
68152
69153template <class _Pair >
70154struct __uses_allocator_construction_args <_Pair, __enable_if_t <__is_cv_std_pair<_Pair>>> {
71155 template <class _Alloc , class _Tuple1 , class _Tuple2 >
72- static _LIBCPP_HIDE_FROM_ABI constexpr auto
156+ static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto
73157 __apply (const _Alloc& __alloc, piecewise_construct_t , _Tuple1&& __x, _Tuple2&& __y) noexcept {
74158 return std::make_tuple (
159+ # if _LIBCPP_STD_VER >= 20
75160 piecewise_construct,
76- std::apply (
161+ # else // _LIBCPP_STD_VER >= 20
162+ std::ref (piecewise_construct),
163+ # endif // _LIBCPP_STD_VER >= 20
164+ __uses_allocator_detail::__apply (
77165 [&__alloc](auto &&... __args1) {
78166 return __uses_allocator_construction_args<typename _Pair::first_type>::__apply (
79167 __alloc, std::forward<decltype (__args1)>(__args1)...);
80168 },
81169 std::forward<_Tuple1>(__x)),
82- std::apply (
170+ __uses_allocator_detail::__apply (
83171 [&__alloc](auto &&... __args2) {
84172 return __uses_allocator_construction_args<typename _Pair::second_type>::__apply (
85173 __alloc, std::forward<decltype (__args2)>(__args2)...);
@@ -88,12 +176,13 @@ struct __uses_allocator_construction_args<_Pair, __enable_if_t<__is_cv_std_pair<
88176 }
89177
90178 template <class _Alloc >
91- static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply (const _Alloc& __alloc) noexcept {
179+ static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto __apply (const _Alloc& __alloc) noexcept {
92180 return __uses_allocator_construction_args<_Pair>::__apply (__alloc, piecewise_construct, tuple<>{}, tuple<>{});
93181 }
94182
95183 template <class _Alloc , class _Up , class _Vp >
96- static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply (const _Alloc& __alloc, _Up&& __u, _Vp&& __v) noexcept {
184+ static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto
185+ __apply (const _Alloc& __alloc, _Up&& __u, _Vp&& __v) noexcept {
97186 return __uses_allocator_construction_args<_Pair>::__apply (
98187 __alloc,
99188 piecewise_construct,
@@ -110,13 +199,15 @@ struct __uses_allocator_construction_args<_Pair, __enable_if_t<__is_cv_std_pair<
110199# endif
111200
112201 template <class _Alloc , class _Up , class _Vp >
113- static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply (const _Alloc& __alloc, const pair<_Up, _Vp>& __pair) noexcept {
202+ static _LIBCPP_HIDE_FROM_ABI
203+ _LIBCPP_CONSTEXPR_SINCE_CXX17 auto __apply (const _Alloc& __alloc, const pair<_Up, _Vp>& __pair) noexcept {
114204 return __uses_allocator_construction_args<_Pair>::__apply (
115205 __alloc, piecewise_construct, std::forward_as_tuple (__pair.first ), std::forward_as_tuple (__pair.second ));
116206 }
117207
118208 template <class _Alloc , class _Up , class _Vp >
119- static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply (const _Alloc& __alloc, pair<_Up, _Vp>&& __pair) noexcept {
209+ static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto
210+ __apply (const _Alloc& __alloc, pair<_Up, _Vp>&& __pair) noexcept {
120211 return __uses_allocator_construction_args<_Pair>::__apply (
121212 __alloc,
122213 piecewise_construct,
@@ -135,7 +226,8 @@ struct __uses_allocator_construction_args<_Pair, __enable_if_t<__is_cv_std_pair<
135226 }
136227
137228 template < class _Alloc , __pair_like_no_subrange _PairLike>
138- static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply (const _Alloc& __alloc, _PairLike&& __p) noexcept {
229+ static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto
230+ __apply (const _Alloc& __alloc, _PairLike&& __p) noexcept {
139231 return __uses_allocator_construction_args<_Pair>::__apply (
140232 __alloc,
141233 piecewise_construct,
@@ -147,22 +239,25 @@ struct __uses_allocator_construction_args<_Pair, __enable_if_t<__is_cv_std_pair<
147239 template <class _Alloc ,
148240 class _Type ,
149241 __enable_if_t <__uses_allocator_detail::__uses_allocator_constraints<_Pair, _Type>, int > = 0 >
150- static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply (const _Alloc& __alloc, _Type&& __value) noexcept {
242+ static _LIBCPP_HIDE_FROM_ABI
243+ _LIBCPP_CONSTEXPR_SINCE_CXX17 auto __apply (const _Alloc& __alloc, _Type&& __value) noexcept {
151244 struct __pair_constructor {
152245 using _PairMutable = remove_cv_t <_Pair>;
153246
154- _LIBCPP_HIDDEN constexpr auto __do_construct (const _PairMutable& __pair) const {
247+ _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX17 auto __do_construct (const _PairMutable& __pair) const {
155248 return std::__make_obj_using_allocator<_PairMutable>(__alloc_, __pair);
156249 }
157250
158- _LIBCPP_HIDDEN constexpr auto __do_construct (_PairMutable&& __pair) const {
251+ _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX17 auto __do_construct (_PairMutable&& __pair) const {
159252 return std::__make_obj_using_allocator<_PairMutable>(__alloc_, std::move (__pair));
160253 }
161254
162255 const _Alloc& __alloc_;
163256 _Type& __value_;
164257
165- _LIBCPP_HIDDEN constexpr operator _PairMutable () const { return __do_construct (std::forward<_Type>(__value_)); }
258+ _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX17 operator _PairMutable () const {
259+ return __do_construct (std::forward<_Type>(__value_));
260+ }
166261 };
167262
168263 return std::make_tuple (__pair_constructor{__alloc, __value});
@@ -172,14 +267,15 @@ struct __uses_allocator_construction_args<_Pair, __enable_if_t<__is_cv_std_pair<
172267template <class _Type >
173268struct __uses_allocator_construction_args <_Type, __enable_if_t <!__is_cv_std_pair<_Type>>> {
174269 template <class _Alloc , class ... _Args>
175- static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply (const _Alloc& __alloc, _Args&&... __args) noexcept {
176- if constexpr (!uses_allocator_v<remove_cv_t <_Type>, _Alloc> && is_constructible_v<_Type, _Args...>) {
270+ static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto
271+ __apply (const _Alloc& __alloc, _Args&&... __args) noexcept {
272+ if constexpr (!uses_allocator<remove_cv_t <_Type>, _Alloc>::value && is_constructible<_Type, _Args...>::value) {
177273 return std::forward_as_tuple (std::forward<_Args>(__args)...);
178- } else if constexpr (uses_allocator_v <remove_cv_t <_Type>, _Alloc> &&
179- is_constructible_v <_Type, allocator_arg_t , const _Alloc&, _Args...>) {
274+ } else if constexpr (uses_allocator <remove_cv_t <_Type>, _Alloc>::value &&
275+ is_constructible <_Type, allocator_arg_t , const _Alloc&, _Args...>::value ) {
180276 return tuple<allocator_arg_t , const _Alloc&, _Args&&...>(allocator_arg, __alloc, std::forward<_Args>(__args)...);
181- } else if constexpr (uses_allocator_v <remove_cv_t <_Type>, _Alloc> &&
182- is_constructible_v <_Type, _Args..., const _Alloc&>) {
277+ } else if constexpr (uses_allocator <remove_cv_t <_Type>, _Alloc>::value &&
278+ is_constructible <_Type, _Args..., const _Alloc&>::value ) {
183279 return std::forward_as_tuple (std::forward<_Args>(__args)..., __alloc);
184280 } else {
185281 static_assert (
@@ -189,19 +285,34 @@ struct __uses_allocator_construction_args<_Type, __enable_if_t<!__is_cv_std_pair
189285};
190286
191287template <class _Type , class _Alloc , class ... _Args>
192- _LIBCPP_HIDE_FROM_ABI constexpr _Type __make_obj_using_allocator (const _Alloc& __alloc, _Args&&... __args) {
193- return std::make_from_tuple<_Type>(
288+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _Type
289+ __make_obj_using_allocator (const _Alloc& __alloc, _Args&&... __args) {
290+ return __uses_allocator_detail::__make_from_tuple<_Type>(
194291 __uses_allocator_construction_args<_Type>::__apply (__alloc, std::forward<_Args>(__args)...));
195292}
196293
294+ #endif // _LIBCPP_STD_VER >= 14
295+
296+ #if _LIBCPP_STD_VER >= 17
297+
197298template <class _Type , class _Alloc , class ... _Args>
198- _LIBCPP_HIDE_FROM_ABI constexpr _Type*
299+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Type*
199300__uninitialized_construct_using_allocator (_Type* __ptr, const _Alloc& __alloc, _Args&&... __args) {
200301 return std::apply (
201302 [&__ptr](auto &&... __xs) { return std::__construct_at (__ptr, std::forward<decltype (__xs)>(__xs)...); },
202303 __uses_allocator_construction_args<_Type>::__apply (__alloc, std::forward<_Args>(__args)...));
203304}
204305
306+ template <class _Type , class _Alloc , class ... _Args>
307+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Type*
308+ __uninitialized_construct_using_allocator_nocv (_Type* __ptr, const _Alloc& __alloc, _Args&&... __args) {
309+ return std::apply (
310+ [&__ptr](auto &&... __xs) {
311+ return __uses_allocator_detail::__construct_at_nocv (__ptr, std::forward<decltype (__xs)>(__xs)...);
312+ },
313+ __uses_allocator_construction_args<_Type>::__apply (__alloc, std::forward<_Args>(__args)...));
314+ }
315+
205316#endif // _LIBCPP_STD_VER >= 17
206317
207318#if _LIBCPP_STD_VER >= 20
0 commit comments