Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / include / __memory / uses_allocator_construction.h
blob71ae5bcd323315bf98cab86bd4a7f759b34248d7
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 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H
10 #define _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H
12 #include <__config>
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>
21 #include <tuple>
23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24 # pragma GCC system_header
25 #endif
27 _LIBCPP_PUSH_MACROS
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;
40 template <class _Tp>
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);
54 } else {
55 static_assert(
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(
64 piecewise_construct,
65 std::apply(
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)),
71 std::apply(
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>(
88 __alloc,
89 piecewise_construct,
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));
101 # endif
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>(
114 __alloc,
115 piecewise_construct,
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>(
125 __alloc,
126 piecewise_construct,
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,
132 class _Alloc,
133 __pair_like _PairLike,
134 __enable_if_t<__is_cv_std_pair<_Pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value,
135 int> = 0>
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>(
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))));
144 # endif
146 namespace __uses_allocator_detail {
148 template <class _Ap, class _Bp>
149 void __fun(const pair<_Ap, _Bp>&);
151 template <class _Tp>
152 decltype(__uses_allocator_detail::__fun(std::declval<_Tp>()), true_type()) __convertible_to_const_pair_ref_impl(int);
154 template <class>
155 false_type __convertible_to_const_pair_ref_impl(...);
157 template <class _Tp>
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>));
167 # else
168 template <class _Tp, class _Up>
169 inline constexpr bool __uses_allocator_constraints = __is_cv_std_pair<_Tp> && !__convertible_to_const_pair_ref<_Up>;
170 # endif
172 } // namespace __uses_allocator_detail
174 template < class _Pair,
175 class _Alloc,
176 class _Type,
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,
185 class _Alloc,
186 class _Type,
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_;
202 _Type& __value_;
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) {
221 return std::apply(
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
253 _LIBCPP_POP_MACROS
255 #endif // _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H