1 // Utility functions for uses-allocator construction -*- C++ -*-
3 // Copyright (C) 2019-2023 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file include/bits/uses_allocator_args.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
30 #ifndef _USES_ALLOCATOR_ARGS
31 #define _USES_ALLOCATOR_ARGS 1
33 #pragma GCC system_header
35 #include <bits/version.h>
37 #ifdef __glibcxx_make_obj_using_allocator // C++ >= 20 && concepts
38 #include <new> // for placement operator new
39 #include <tuple> // for tuple, make_tuple, make_from_tuple
40 #include <bits/stl_construct.h> // construct_at
41 #include <bits/stl_pair.h> // pair
43 namespace std
_GLIBCXX_VISIBILITY(default)
45 _GLIBCXX_BEGIN_NAMESPACE_VERSION
47 template<typename _Tp
>
48 concept _Std_pair
= __is_pair
<remove_cv_t
<_Tp
>>;
50 /** @addtogroup allocators
53 template<typename _Tp
, typename _Alloc
, typename
... _Args
>
55 uses_allocator_construction_args(const _Alloc
& __a
,
56 _Args
&&... __args
) noexcept
57 requires (! _Std_pair
<_Tp
>)
59 if constexpr (uses_allocator_v
<remove_cv_t
<_Tp
>, _Alloc
>)
61 if constexpr (is_constructible_v
<_Tp
, allocator_arg_t
,
62 const _Alloc
&, _Args
...>)
64 return tuple
<allocator_arg_t
, const _Alloc
&, _Args
&&...>(
65 allocator_arg
, __a
, std::forward
<_Args
>(__args
)...);
69 static_assert(is_constructible_v
<_Tp
, _Args
..., const _Alloc
&>,
70 "construction with an allocator must be possible"
71 " if uses_allocator is true");
73 return tuple
<_Args
&&..., const _Alloc
&>(
74 std::forward
<_Args
>(__args
)..., __a
);
79 static_assert(is_constructible_v
<_Tp
, _Args
...>);
81 return tuple
<_Args
&&...>(std::forward
<_Args
>(__args
)...);
85 template<_Std_pair _Tp
, typename _Alloc
, typename _Tuple1
, typename _Tuple2
>
87 uses_allocator_construction_args(const _Alloc
& __a
, piecewise_construct_t
,
88 _Tuple1
&& __x
, _Tuple2
&& __y
) noexcept
;
90 template<_Std_pair _Tp
, typename _Alloc
>
92 uses_allocator_construction_args(const _Alloc
&) noexcept
;
94 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
96 uses_allocator_construction_args(const _Alloc
&, _Up
&&, _Vp
&&) noexcept
;
98 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
100 uses_allocator_construction_args(const _Alloc
&,
101 const pair
<_Up
, _Vp
>&) noexcept
;
103 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
105 uses_allocator_construction_args(const _Alloc
&, pair
<_Up
, _Vp
>&&) noexcept
;
107 #if __cplusplus > 202002L
108 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
110 uses_allocator_construction_args(const _Alloc
&,
111 pair
<_Up
, _Vp
>&) noexcept
;
113 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
115 uses_allocator_construction_args(const _Alloc
&, const pair
<_Up
, _Vp
>&&) noexcept
;
118 template<_Std_pair _Tp
, typename _Alloc
, typename _Tuple1
, typename _Tuple2
>
120 uses_allocator_construction_args(const _Alloc
& __a
, piecewise_construct_t
,
121 _Tuple1
&& __x
, _Tuple2
&& __y
) noexcept
123 using _Tp1
= typename
_Tp::first_type
;
124 using _Tp2
= typename
_Tp::second_type
;
126 return std::make_tuple(piecewise_construct
,
127 std::apply([&__a
](auto&&... __args1
) {
128 return std::uses_allocator_construction_args
<_Tp1
>(
129 __a
, std::forward
<decltype(__args1
)>(__args1
)...);
130 }, std::forward
<_Tuple1
>(__x
)),
131 std::apply([&__a
](auto&&... __args2
) {
132 return std::uses_allocator_construction_args
<_Tp2
>(
133 __a
, std::forward
<decltype(__args2
)>(__args2
)...);
134 }, std::forward
<_Tuple2
>(__y
)));
137 template<_Std_pair _Tp
, typename _Alloc
>
139 uses_allocator_construction_args(const _Alloc
& __a
) noexcept
141 using _Tp1
= typename
_Tp::first_type
;
142 using _Tp2
= typename
_Tp::second_type
;
144 return std::make_tuple(piecewise_construct
,
145 std::uses_allocator_construction_args
<_Tp1
>(__a
),
146 std::uses_allocator_construction_args
<_Tp2
>(__a
));
149 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
151 uses_allocator_construction_args(const _Alloc
& __a
, _Up
&& __u
, _Vp
&& __v
)
154 using _Tp1
= typename
_Tp::first_type
;
155 using _Tp2
= typename
_Tp::second_type
;
157 return std::make_tuple(piecewise_construct
,
158 std::uses_allocator_construction_args
<_Tp1
>(__a
,
159 std::forward
<_Up
>(__u
)),
160 std::uses_allocator_construction_args
<_Tp2
>(__a
,
161 std::forward
<_Vp
>(__v
)));
164 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
166 uses_allocator_construction_args(const _Alloc
& __a
,
167 const pair
<_Up
, _Vp
>& __pr
) noexcept
169 using _Tp1
= typename
_Tp::first_type
;
170 using _Tp2
= typename
_Tp::second_type
;
172 return std::make_tuple(piecewise_construct
,
173 std::uses_allocator_construction_args
<_Tp1
>(__a
, __pr
.first
),
174 std::uses_allocator_construction_args
<_Tp2
>(__a
, __pr
.second
));
177 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
179 uses_allocator_construction_args(const _Alloc
& __a
,
180 pair
<_Up
, _Vp
>&& __pr
) noexcept
182 using _Tp1
= typename
_Tp::first_type
;
183 using _Tp2
= typename
_Tp::second_type
;
185 // _GLIBCXX_RESOLVE_LIB_DEFECTS
186 // 3527. uses_allocator_construction_args handles rvalue pairs
187 // of rvalue references incorrectly
188 return std::make_tuple(piecewise_construct
,
189 std::uses_allocator_construction_args
<_Tp1
>(__a
,
190 std::get
<0>(std::move(__pr
))),
191 std::uses_allocator_construction_args
<_Tp2
>(__a
,
192 std::get
<1>(std::move(__pr
))));
195 #if __cplusplus > 202002L
196 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
198 uses_allocator_construction_args(const _Alloc
& __a
,
199 pair
<_Up
, _Vp
>& __pr
) noexcept
201 using _Tp1
= typename
_Tp::first_type
;
202 using _Tp2
= typename
_Tp::second_type
;
204 return std::make_tuple(piecewise_construct
,
205 std::uses_allocator_construction_args
<_Tp1
>(__a
, __pr
.first
),
206 std::uses_allocator_construction_args
<_Tp2
>(__a
, __pr
.second
));
209 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
211 uses_allocator_construction_args(const _Alloc
& __a
,
212 const pair
<_Up
, _Vp
>&& __pr
) noexcept
214 using _Tp1
= typename
_Tp::first_type
;
215 using _Tp2
= typename
_Tp::second_type
;
217 return std::make_tuple(piecewise_construct
,
218 std::uses_allocator_construction_args
<_Tp1
>(__a
,
219 std::get
<0>(std::move(__pr
))),
220 std::uses_allocator_construction_args
<_Tp2
>(__a
,
221 std::get
<1>(std::move(__pr
))));
225 template<typename _Tp
, typename _Alloc
, typename
... _Args
>
227 make_obj_using_allocator(const _Alloc
& __a
, _Args
&&... __args
)
229 return std::make_from_tuple
<_Tp
>(
230 std::uses_allocator_construction_args
<_Tp
>(__a
,
231 std::forward
<_Args
>(__args
)...));
234 template<typename _Tp
, typename _Alloc
, typename
... _Args
>
236 uninitialized_construct_using_allocator(_Tp
* __p
, const _Alloc
& __a
,
239 return std::apply([&](auto&&... __xs
) {
240 return std::construct_at(__p
, std::forward
<decltype(__xs
)>(__xs
)...);
241 }, std::uses_allocator_construction_args
<_Tp
>(__a
,
242 std::forward
<_Args
>(__args
)...));
245 _GLIBCXX_END_NAMESPACE_VERSION
247 #endif // __glibcxx_make_obj_using_allocator
248 #endif // _USES_ALLOCATOR_ARGS