1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H
10 #define _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H
13 #include <__memory/construct_at.h>
14 #include <__memory/uses_allocator.h>
15 #include <__tuple/pair_like.h>
16 #include <__type_traits/enable_if.h>
17 #include <__type_traits/is_same.h>
18 #include <__type_traits/remove_cv.h>
19 #include <__utility/declval.h>
20 #include <__utility/pair.h>
23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24 # pragma GCC system_header
28 #include <__undef_macros>
30 _LIBCPP_BEGIN_NAMESPACE_STD
32 #if _LIBCPP_STD_VER >= 17
34 template <class _Type
>
35 inline constexpr bool __is_std_pair
= false;
37 template <class _Type1
, class _Type2
>
38 inline constexpr bool __is_std_pair
<pair
<_Type1
, _Type2
>> = true;
41 inline constexpr bool __is_cv_std_pair
= __is_std_pair
<remove_cv_t
<_Tp
>>;
43 template <class _Type
, class _Alloc
, class... _Args
, __enable_if_t
<!__is_cv_std_pair
<_Type
>, int> = 0>
44 _LIBCPP_HIDE_FROM_ABI
constexpr auto
45 __uses_allocator_construction_args(const _Alloc
& __alloc
, _Args
&&... __args
) noexcept
{
46 if constexpr (!uses_allocator_v
<remove_cv_t
<_Type
>, _Alloc
> && is_constructible_v
<_Type
, _Args
...>) {
47 return std::forward_as_tuple(std::forward
<_Args
>(__args
)...);
48 } else if constexpr (uses_allocator_v
<remove_cv_t
<_Type
>, _Alloc
> &&
49 is_constructible_v
<_Type
, allocator_arg_t
, const _Alloc
&, _Args
...>) {
50 return tuple
<allocator_arg_t
, const _Alloc
&, _Args
&&...>(allocator_arg
, __alloc
, std::forward
<_Args
>(__args
)...);
51 } else if constexpr (uses_allocator_v
<remove_cv_t
<_Type
>, _Alloc
> &&
52 is_constructible_v
<_Type
, _Args
..., const _Alloc
&>) {
53 return std::forward_as_tuple(std::forward
<_Args
>(__args
)..., __alloc
);
56 sizeof(_Type
) + 1 == 0, "If uses_allocator_v<Type> is true, the type has to be allocator-constructible");
60 template <class _Pair
, class _Alloc
, class _Tuple1
, class _Tuple2
, __enable_if_t
<__is_cv_std_pair
<_Pair
>, int> = 0>
61 _LIBCPP_HIDE_FROM_ABI
constexpr auto __uses_allocator_construction_args(
62 const _Alloc
& __alloc
, piecewise_construct_t
, _Tuple1
&& __x
, _Tuple2
&& __y
) noexcept
{
63 return std::make_tuple(
66 [&__alloc
](auto&&... __args1
) {
67 return std::__uses_allocator_construction_args
<typename
_Pair::first_type
>(
68 __alloc
, std::forward
<decltype(__args1
)>(__args1
)...);
70 std::forward
<_Tuple1
>(__x
)),
72 [&__alloc
](auto&&... __args2
) {
73 return std::__uses_allocator_construction_args
<typename
_Pair::second_type
>(
74 __alloc
, std::forward
<decltype(__args2
)>(__args2
)...);
76 std::forward
<_Tuple2
>(__y
)));
79 template <class _Pair
, class _Alloc
, __enable_if_t
<__is_cv_std_pair
<_Pair
>, int> = 0>
80 _LIBCPP_HIDE_FROM_ABI
constexpr auto __uses_allocator_construction_args(const _Alloc
& __alloc
) noexcept
{
81 return std::__uses_allocator_construction_args
<_Pair
>(__alloc
, piecewise_construct
, tuple
<>{}, tuple
<>{});
84 template <class _Pair
, class _Alloc
, class _Up
, class _Vp
, __enable_if_t
<__is_cv_std_pair
<_Pair
>, int> = 0>
85 _LIBCPP_HIDE_FROM_ABI
constexpr auto
86 __uses_allocator_construction_args(const _Alloc
& __alloc
, _Up
&& __u
, _Vp
&& __v
) noexcept
{
87 return std::__uses_allocator_construction_args
<_Pair
>(
90 std::forward_as_tuple(std::forward
<_Up
>(__u
)),
91 std::forward_as_tuple(std::forward
<_Vp
>(__v
)));
94 # if _LIBCPP_STD_VER >= 23
95 template <class _Pair
, class _Alloc
, class _Up
, class _Vp
, __enable_if_t
<__is_cv_std_pair
<_Pair
>, int> = 0>
96 _LIBCPP_HIDE_FROM_ABI
constexpr auto
97 __uses_allocator_construction_args(const _Alloc
& __alloc
, pair
<_Up
, _Vp
>& __pair
) noexcept
{
98 return std::__uses_allocator_construction_args
<_Pair
>(
99 __alloc
, piecewise_construct
, std::forward_as_tuple(__pair
.first
), std::forward_as_tuple(__pair
.second
));
103 template <class _Pair
, class _Alloc
, class _Up
, class _Vp
, __enable_if_t
<__is_cv_std_pair
<_Pair
>, int> = 0>
104 _LIBCPP_HIDE_FROM_ABI
constexpr auto
105 __uses_allocator_construction_args(const _Alloc
& __alloc
, const pair
<_Up
, _Vp
>& __pair
) noexcept
{
106 return std::__uses_allocator_construction_args
<_Pair
>(
107 __alloc
, piecewise_construct
, std::forward_as_tuple(__pair
.first
), std::forward_as_tuple(__pair
.second
));
110 template <class _Pair
, class _Alloc
, class _Up
, class _Vp
, __enable_if_t
<__is_cv_std_pair
<_Pair
>, int> = 0>
111 _LIBCPP_HIDE_FROM_ABI
constexpr auto
112 __uses_allocator_construction_args(const _Alloc
& __alloc
, pair
<_Up
, _Vp
>&& __pair
) noexcept
{
113 return std::__uses_allocator_construction_args
<_Pair
>(
116 std::forward_as_tuple(std::get
<0>(std::move(__pair
))),
117 std::forward_as_tuple(std::get
<1>(std::move(__pair
))));
120 # if _LIBCPP_STD_VER >= 23
121 template <class _Pair
, class _Alloc
, class _Up
, class _Vp
, __enable_if_t
<__is_cv_std_pair
<_Pair
>, int> = 0>
122 _LIBCPP_HIDE_FROM_ABI
constexpr auto
123 __uses_allocator_construction_args(const _Alloc
& __alloc
, const pair
<_Up
, _Vp
>&& __pair
) noexcept
{
124 return std::__uses_allocator_construction_args
<_Pair
>(
127 std::forward_as_tuple(std::get
<0>(std::move(__pair
))),
128 std::forward_as_tuple(std::get
<1>(std::move(__pair
))));
131 template < class _Pair
,
133 __pair_like _PairLike
,
134 __enable_if_t
<__is_cv_std_pair
<_Pair
> && !__is_specialization_of_subrange
<remove_cvref_t
<_PairLike
>>::value
,
136 _LIBCPP_HIDE_FROM_ABI
constexpr auto
137 __uses_allocator_construction_args(const _Alloc
& __alloc
, _PairLike
&& __p
) noexcept
{
138 return std::__uses_allocator_construction_args
<_Pair
>(
141 std::forward_as_tuple(std::get
<0>(std::forward
<_PairLike
>(__p
))),
142 std::forward_as_tuple(std::get
<1>(std::forward
<_PairLike
>(__p
))));
146 namespace __uses_allocator_detail
{
148 template <class _Ap
, class _Bp
>
149 void __fun(const pair
<_Ap
, _Bp
>&);
152 decltype(__uses_allocator_detail::__fun(std::declval
<_Tp
>()), true_type()) __convertible_to_const_pair_ref_impl(int);
155 false_type
__convertible_to_const_pair_ref_impl(...);
158 inline constexpr bool __convertible_to_const_pair_ref
=
159 decltype(__uses_allocator_detail::__convertible_to_const_pair_ref_impl
<_Tp
>(0))::value
;
161 # if _LIBCPP_STD_VER >= 23
162 template <class _Tp
, class _Up
>
163 inline constexpr bool __uses_allocator_constraints
=
164 __is_cv_std_pair
<_Tp
> &&
165 (__is_specialization_of_subrange
<remove_cvref_t
<_Up
>>::value
||
166 (!__pair_like
<_Up
> && !__convertible_to_const_pair_ref
<_Up
>));
168 template <class _Tp
, class _Up
>
169 inline constexpr bool __uses_allocator_constraints
= __is_cv_std_pair
<_Tp
> && !__convertible_to_const_pair_ref
<_Up
>;
172 } // namespace __uses_allocator_detail
174 template < class _Pair
,
177 __enable_if_t
<__uses_allocator_detail::__uses_allocator_constraints
<_Pair
, _Type
>, int> = 0>
178 _LIBCPP_HIDE_FROM_ABI
constexpr auto
179 __uses_allocator_construction_args(const _Alloc
& __alloc
, _Type
&& __value
) noexcept
;
181 template <class _Type
, class _Alloc
, class... _Args
>
182 _LIBCPP_HIDE_FROM_ABI
constexpr _Type
__make_obj_using_allocator(const _Alloc
& __alloc
, _Args
&&... __args
);
184 template < class _Pair
,
187 __enable_if_t
< __uses_allocator_detail::__uses_allocator_constraints
<_Pair
, _Type
>, int>>
188 _LIBCPP_HIDE_FROM_ABI
constexpr auto
189 __uses_allocator_construction_args(const _Alloc
& __alloc
, _Type
&& __value
) noexcept
{
190 struct __pair_constructor
{
191 using _PairMutable
= remove_cv_t
<_Pair
>;
193 _LIBCPP_HIDE_FROM_ABI
constexpr auto __do_construct(const _PairMutable
& __pair
) const {
194 return std::__make_obj_using_allocator
<_PairMutable
>(__alloc_
, __pair
);
197 _LIBCPP_HIDE_FROM_ABI
constexpr auto __do_construct(_PairMutable
&& __pair
) const {
198 return std::__make_obj_using_allocator
<_PairMutable
>(__alloc_
, std::move(__pair
));
201 const _Alloc
& __alloc_
;
204 _LIBCPP_HIDE_FROM_ABI
constexpr operator _PairMutable() const {
205 return __do_construct(std::forward
<_Type
>(this->__value_
));
209 return std::make_tuple(__pair_constructor
{__alloc
, __value
});
212 template <class _Type
, class _Alloc
, class... _Args
>
213 _LIBCPP_HIDE_FROM_ABI
constexpr _Type
__make_obj_using_allocator(const _Alloc
& __alloc
, _Args
&&... __args
) {
214 return std::make_from_tuple
<_Type
>(
215 std::__uses_allocator_construction_args
<_Type
>(__alloc
, std::forward
<_Args
>(__args
)...));
218 template <class _Type
, class _Alloc
, class... _Args
>
219 _LIBCPP_HIDE_FROM_ABI
constexpr _Type
*
220 __uninitialized_construct_using_allocator(_Type
* __ptr
, const _Alloc
& __alloc
, _Args
&&... __args
) {
222 [&__ptr
](auto&&... __xs
) { return std::__construct_at(__ptr
, std::forward
<decltype(__xs
)>(__xs
)...); },
223 std::__uses_allocator_construction_args
<_Type
>(__alloc
, std::forward
<_Args
>(__args
)...));
226 #endif // _LIBCPP_STD_VER >= 17
228 #if _LIBCPP_STD_VER >= 20
230 template <class _Type
, class _Alloc
, class... _Args
>
231 _LIBCPP_HIDE_FROM_ABI
constexpr auto uses_allocator_construction_args(const _Alloc
& __alloc
, _Args
&&... __args
) noexcept
232 -> decltype(std::__uses_allocator_construction_args
<_Type
>(__alloc
, std::forward
<_Args
>(__args
)...)) {
233 return /*--*/ std::__uses_allocator_construction_args
<_Type
>(__alloc
, std::forward
<_Args
>(__args
)...);
236 template <class _Type
, class _Alloc
, class... _Args
>
237 _LIBCPP_HIDE_FROM_ABI
constexpr auto make_obj_using_allocator(const _Alloc
& __alloc
, _Args
&&... __args
)
238 -> decltype(std::__make_obj_using_allocator
<_Type
>(__alloc
, std::forward
<_Args
>(__args
)...)) {
239 return /*--*/ std::__make_obj_using_allocator
<_Type
>(__alloc
, std::forward
<_Args
>(__args
)...);
242 template <class _Type
, class _Alloc
, class... _Args
>
243 _LIBCPP_HIDE_FROM_ABI
constexpr auto
244 uninitialized_construct_using_allocator(_Type
* __ptr
, const _Alloc
& __alloc
, _Args
&&... __args
)
245 -> decltype(std::__uninitialized_construct_using_allocator(__ptr
, __alloc
, std::forward
<_Args
>(__args
)...)) {
246 return /*--*/ std::__uninitialized_construct_using_allocator(__ptr
, __alloc
, std::forward
<_Args
>(__args
)...);
249 #endif // _LIBCPP_STD_VER >= 20
251 _LIBCPP_END_NAMESPACE_STD
255 #endif // _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H