1 // Utility functions for uses-allocator construction -*- C++ -*-
3 // Copyright (C) 2019-2021 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/>.
26 * Copyright (c) 1997-1999
27 * Silicon Graphics Computer Systems, Inc.
29 * Permission to use, copy, modify, distribute and sell this software
30 * and its documentation for any purpose is hereby granted without fee,
31 * provided that the above copyright notice appear in all copies and
32 * that both that copyright notice and this permission notice appear
33 * in supporting documentation. Silicon Graphics makes no
34 * representations about the suitability of this software for any
35 * purpose. It is provided "as is" without express or implied warranty.
39 /** @file include/bits/uses_allocator_args.h
40 * This is an internal header file, included by other library headers.
41 * Do not attempt to use it directly. @headername{memory}
44 #ifndef _USES_ALLOCATOR_ARGS
45 #define _USES_ALLOCATOR_ARGS 1
47 #pragma GCC system_header
49 #if __cplusplus > 201703L && __cpp_concepts
51 #include <new> // for placement operator new
52 #include <tuple> // for tuple, make_tuple, make_from_tuple
53 #include <bits/stl_construct.h> // construct_at
54 #include <bits/stl_pair.h> // pair
56 namespace std
_GLIBCXX_VISIBILITY(default)
58 _GLIBCXX_BEGIN_NAMESPACE_VERSION
59 template<typename _Tp
>
60 inline constexpr bool __is_pair
= false;
61 template<typename _Tp
, typename _Up
>
62 inline constexpr bool __is_pair
<pair
<_Tp
, _Up
>> = true;
63 template<typename _Tp
, typename _Up
>
64 inline constexpr bool __is_pair
<const pair
<_Tp
, _Up
>> = true;
66 template<typename _Tp
>
67 concept _Std_pair
= __is_pair
<_Tp
>;
69 /** @addtogroup allocators
73 // Not specified by C++20, used internally
74 #define __cpp_lib_make_obj_using_allocator 201811L
76 template<typename _Tp
, typename _Alloc
, typename
... _Args
>
78 uses_allocator_construction_args(const _Alloc
& __a
,
79 _Args
&&... __args
) noexcept
80 requires (! _Std_pair
<_Tp
>)
82 if constexpr (uses_allocator_v
<remove_cv_t
<_Tp
>, _Alloc
>)
84 if constexpr (is_constructible_v
<_Tp
, allocator_arg_t
,
85 const _Alloc
&, _Args
...>)
87 return tuple
<allocator_arg_t
, const _Alloc
&, _Args
&&...>(
88 allocator_arg
, __a
, std::forward
<_Args
>(__args
)...);
92 static_assert(is_constructible_v
<_Tp
, _Args
..., const _Alloc
&>,
93 "construction with an allocator must be possible"
94 " if uses_allocator is true");
96 return tuple
<_Args
&&..., const _Alloc
&>(
97 std::forward
<_Args
>(__args
)..., __a
);
102 static_assert(is_constructible_v
<_Tp
, _Args
...>);
104 return tuple
<_Args
&&...>(std::forward
<_Args
>(__args
)...);
108 template<_Std_pair _Tp
, typename _Alloc
, typename _Tuple1
, typename _Tuple2
>
110 uses_allocator_construction_args(const _Alloc
& __a
, piecewise_construct_t
,
111 _Tuple1
&& __x
, _Tuple2
&& __y
) noexcept
;
113 template<_Std_pair _Tp
, typename _Alloc
>
115 uses_allocator_construction_args(const _Alloc
&) noexcept
;
117 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
119 uses_allocator_construction_args(const _Alloc
&, _Up
&&, _Vp
&&) noexcept
;
121 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
123 uses_allocator_construction_args(const _Alloc
&,
124 const pair
<_Up
, _Vp
>&) noexcept
;
126 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
128 uses_allocator_construction_args(const _Alloc
&, pair
<_Up
, _Vp
>&&) noexcept
;
130 template<_Std_pair _Tp
, typename _Alloc
, typename _Tuple1
, typename _Tuple2
>
132 uses_allocator_construction_args(const _Alloc
& __a
, piecewise_construct_t
,
133 _Tuple1
&& __x
, _Tuple2
&& __y
) noexcept
135 using _Tp1
= typename
_Tp::first_type
;
136 using _Tp2
= typename
_Tp::second_type
;
138 return std::make_tuple(piecewise_construct
,
139 std::apply([&__a
](auto&&... __args1
) {
140 return std::uses_allocator_construction_args
<_Tp1
>(
141 __a
, std::forward
<decltype(__args1
)>(__args1
)...);
142 }, std::forward
<_Tuple1
>(__x
)),
143 std::apply([&__a
](auto&&... __args2
) {
144 return std::uses_allocator_construction_args
<_Tp2
>(
145 __a
, std::forward
<decltype(__args2
)>(__args2
)...);
146 }, std::forward
<_Tuple2
>(__y
)));
149 template<_Std_pair _Tp
, typename _Alloc
>
151 uses_allocator_construction_args(const _Alloc
& __a
) noexcept
153 using _Tp1
= typename
_Tp::first_type
;
154 using _Tp2
= typename
_Tp::second_type
;
156 return std::make_tuple(piecewise_construct
,
157 std::uses_allocator_construction_args
<_Tp1
>(__a
),
158 std::uses_allocator_construction_args
<_Tp2
>(__a
));
161 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
163 uses_allocator_construction_args(const _Alloc
& __a
, _Up
&& __u
, _Vp
&& __v
)
166 using _Tp1
= typename
_Tp::first_type
;
167 using _Tp2
= typename
_Tp::second_type
;
169 return std::make_tuple(piecewise_construct
,
170 std::uses_allocator_construction_args
<_Tp1
>(__a
,
171 std::forward
<_Up
>(__u
)),
172 std::uses_allocator_construction_args
<_Tp2
>(__a
,
173 std::forward
<_Vp
>(__v
)));
176 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
178 uses_allocator_construction_args(const _Alloc
& __a
,
179 const pair
<_Up
, _Vp
>& __pr
) noexcept
181 using _Tp1
= typename
_Tp::first_type
;
182 using _Tp2
= typename
_Tp::second_type
;
184 return std::make_tuple(piecewise_construct
,
185 std::uses_allocator_construction_args
<_Tp1
>(__a
, __pr
.first
),
186 std::uses_allocator_construction_args
<_Tp2
>(__a
, __pr
.second
));
189 template<_Std_pair _Tp
, typename _Alloc
, typename _Up
, typename _Vp
>
191 uses_allocator_construction_args(const _Alloc
& __a
,
192 pair
<_Up
, _Vp
>&& __pr
) noexcept
194 using _Tp1
= typename
_Tp::first_type
;
195 using _Tp2
= typename
_Tp::second_type
;
197 return std::make_tuple(piecewise_construct
,
198 std::uses_allocator_construction_args
<_Tp1
>(__a
,
199 std::move(__pr
).first
),
200 std::uses_allocator_construction_args
<_Tp2
>(__a
,
201 std::move(__pr
).second
));
204 template<typename _Tp
, typename _Alloc
, typename
... _Args
>
206 make_obj_using_allocator(const _Alloc
& __a
, _Args
&&... __args
)
208 return std::make_from_tuple
<_Tp
>(
209 std::uses_allocator_construction_args
<_Tp
>(__a
,
210 std::forward
<_Args
>(__args
)...));
213 template<typename _Tp
, typename _Alloc
, typename
... _Args
>
215 uninitialized_construct_using_allocator(_Tp
* __p
, const _Alloc
& __a
,
218 return std::apply([&](auto&&... __xs
) {
219 return std::construct_at(__p
, std::forward
<decltype(__xs
)>(__xs
)...);
220 }, std::uses_allocator_construction_args
<_Tp
>(__a
,
221 std::forward
<_Args
>(__args
)...));
224 _GLIBCXX_END_NAMESPACE_VERSION
227 #endif // _USES_ALLOCATOR_ARGS