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.
