libstdc++
uses_allocator_args.h
Go to the documentation of this file.
1// Utility functions for uses-allocator construction -*- C++ -*-
2
3// Copyright (C) 2019-2025 Free Software Foundation, Inc.
4//
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)
9// any later version.
10
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.
15
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.
19
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/>.
24
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}
28 */
29
30#ifndef _USES_ALLOCATOR_ARGS
31#define _USES_ALLOCATOR_ARGS 1
32
33#ifdef _GLIBCXX_SYSHDR
34#pragma GCC system_header
35#endif
36
37#include <bits/version.h>
38
39#ifdef __glibcxx_make_obj_using_allocator // C++ >= 20 && concepts
40#include <new> // for placement operator new
41#include <tuple> // for tuple, make_tuple, make_from_tuple
42#include <bits/stl_construct.h> // construct_at
43#include <bits/stl_pair.h> // pair
44
45namespace std _GLIBCXX_VISIBILITY(default)
46{
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
48
49 template<typename _Tp>
50 concept _Std_pair = __is_pair<remove_cv_t<_Tp>>;
51
52/** @addtogroup allocators
53 * @{
54 */
55 template<typename _Tp, typename _Alloc, typename... _Args>
56 constexpr auto
57 uses_allocator_construction_args(const _Alloc& __a,
58 _Args&&... __args) noexcept
59 requires (! _Std_pair<_Tp>)
60 {
61 if constexpr (uses_allocator_v<remove_cv_t<_Tp>, _Alloc>)
62 {
63 if constexpr (is_constructible_v<_Tp, allocator_arg_t,
64 const _Alloc&, _Args...>)
65 {
66 return tuple<allocator_arg_t, const _Alloc&, _Args&&...>(
67 allocator_arg, __a, std::forward<_Args>(__args)...);
68 }
69 else
70 {
71 static_assert(is_constructible_v<_Tp, _Args..., const _Alloc&>,
72 "construction with an allocator must be possible"
73 " if uses_allocator is true");
74
75 return tuple<_Args&&..., const _Alloc&>(
76 std::forward<_Args>(__args)..., __a);
77 }
78 }
79 else
80 {
81 static_assert(is_constructible_v<_Tp, _Args...>);
82
83 return tuple<_Args&&...>(std::forward<_Args>(__args)...);
84 }
85 }
86
87 template<_Std_pair _Tp, typename _Alloc, typename _Tuple1, typename _Tuple2>
88 constexpr auto
89 uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t,
90 _Tuple1&& __x, _Tuple2&& __y) noexcept;
91
92 template<_Std_pair _Tp, typename _Alloc>
93 constexpr auto
94 uses_allocator_construction_args(const _Alloc&) noexcept;
95
96 template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp>
97 constexpr auto
98 uses_allocator_construction_args(const _Alloc&, _Up&&, _Vp&&) noexcept;
99
100 template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp>
101 constexpr auto
102 uses_allocator_construction_args(const _Alloc&,
103 const pair<_Up, _Vp>&) noexcept;
104
105 template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp>
106 constexpr auto
107 uses_allocator_construction_args(const _Alloc&, pair<_Up, _Vp>&&) noexcept;
108
109#if __cplusplus > 202002L
110 template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp>
111 constexpr auto
112 uses_allocator_construction_args(const _Alloc&,
113 pair<_Up, _Vp>&) noexcept;
114
115 template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp>
116 constexpr auto
117 uses_allocator_construction_args(const _Alloc&, const pair<_Up, _Vp>&&) noexcept;
118#endif // C++23
119
120 template<_Std_pair _Tp, typename _Alloc, typename _Tuple1, typename _Tuple2>
121 constexpr auto
122 uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t,
123 _Tuple1&& __x, _Tuple2&& __y) noexcept
124 {
125 using _Tp1 = typename _Tp::first_type;
126 using _Tp2 = typename _Tp::second_type;
127
129 std::apply([&__a](auto&&... __args1) {
130 return std::uses_allocator_construction_args<_Tp1>(
131 __a, std::forward<decltype(__args1)>(__args1)...);
132 }, std::forward<_Tuple1>(__x)),
133 std::apply([&__a](auto&&... __args2) {
134 return std::uses_allocator_construction_args<_Tp2>(
135 __a, std::forward<decltype(__args2)>(__args2)...);
136 }, std::forward<_Tuple2>(__y)));
137 }
138
139 template<_Std_pair _Tp, typename _Alloc>
140 constexpr auto
141 uses_allocator_construction_args(const _Alloc& __a) noexcept
142 {
143 using _Tp1 = typename _Tp::first_type;
144 using _Tp2 = typename _Tp::second_type;
145
147 std::uses_allocator_construction_args<_Tp1>(__a),
148 std::uses_allocator_construction_args<_Tp2>(__a));
149 }
150
151 template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp>
152 constexpr auto
153 uses_allocator_construction_args(const _Alloc& __a, _Up&& __u, _Vp&& __v)
154 noexcept
155 {
156 using _Tp1 = typename _Tp::first_type;
157 using _Tp2 = typename _Tp::second_type;
158
160 std::uses_allocator_construction_args<_Tp1>(__a,
161 std::forward<_Up>(__u)),
162 std::uses_allocator_construction_args<_Tp2>(__a,
163 std::forward<_Vp>(__v)));
164 }
165
166 template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp>
167 constexpr auto
168 uses_allocator_construction_args(const _Alloc& __a,
169 const pair<_Up, _Vp>& __pr) noexcept
170 {
171 using _Tp1 = typename _Tp::first_type;
172 using _Tp2 = typename _Tp::second_type;
173
175 std::uses_allocator_construction_args<_Tp1>(__a, __pr.first),
176 std::uses_allocator_construction_args<_Tp2>(__a, __pr.second));
177 }
178
179 template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp>
180 constexpr auto
181 uses_allocator_construction_args(const _Alloc& __a,
182 pair<_Up, _Vp>&& __pr) noexcept
183 {
184 using _Tp1 = typename _Tp::first_type;
185 using _Tp2 = typename _Tp::second_type;
186
187 // _GLIBCXX_RESOLVE_LIB_DEFECTS
188 // 3527. uses_allocator_construction_args handles rvalue pairs
189 // of rvalue references incorrectly
191 std::uses_allocator_construction_args<_Tp1>(__a,
192 std::get<0>(std::move(__pr))),
193 std::uses_allocator_construction_args<_Tp2>(__a,
194 std::get<1>(std::move(__pr))));
195 }
196
197#if __cplusplus > 202002L
198 template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp>
199 constexpr auto
200 uses_allocator_construction_args(const _Alloc& __a,
201 pair<_Up, _Vp>& __pr) noexcept
202 {
203 using _Tp1 = typename _Tp::first_type;
204 using _Tp2 = typename _Tp::second_type;
205
207 std::uses_allocator_construction_args<_Tp1>(__a, __pr.first),
208 std::uses_allocator_construction_args<_Tp2>(__a, __pr.second));
209 }
210
211 template<_Std_pair _Tp, typename _Alloc, typename _Up, typename _Vp>
212 constexpr auto
213 uses_allocator_construction_args(const _Alloc& __a,
214 const pair<_Up, _Vp>&& __pr) noexcept
215 {
216 using _Tp1 = typename _Tp::first_type;
217 using _Tp2 = typename _Tp::second_type;
218
220 std::uses_allocator_construction_args<_Tp1>(__a,
221 std::get<0>(std::move(__pr))),
222 std::uses_allocator_construction_args<_Tp2>(__a,
223 std::get<1>(std::move(__pr))));
224 }
225#endif // C++23
226
227 template<typename _Tp, typename _Alloc, typename... _Args>
228 constexpr _Tp
229 make_obj_using_allocator(const _Alloc& __a, _Args&&... __args)
230 {
231 return std::make_from_tuple<_Tp>(
232 std::uses_allocator_construction_args<_Tp>(__a,
233 std::forward<_Args>(__args)...));
234 }
235
236 template<typename _Tp, typename _Alloc, typename... _Args>
237 constexpr _Tp*
238 uninitialized_construct_using_allocator(_Tp* __p, const _Alloc& __a,
239 _Args&&... __args)
240 {
241 return std::apply([&](auto&&... __xs) {
242 return std::construct_at(__p, std::forward<decltype(__xs)>(__xs)...);
243 }, std::uses_allocator_construction_args<_Tp>(__a,
244 std::forward<_Args>(__args)...));
245 }
246/// @}
247_GLIBCXX_END_NAMESPACE_VERSION
248} // namespace std
249#endif // __glibcxx_make_obj_using_allocator
250#endif // _USES_ALLOCATOR_ARGS
constexpr tuple< typename __decay_and_strip< _Elements >::__type... > make_tuple(_Elements &&... __args)
Create a tuple containing copies of the arguments.
Definition tuple:2668
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:138
constexpr piecewise_construct_t piecewise_construct
Tag for piecewise construction of std::pair objects.
Definition stl_pair.h:82
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:72
ISO C++ entities toplevel namespace is std.
Primary class template, tuple.
Definition tuple:834
Struct holding two objects of arbitrary type.
Definition stl_pair.h:304
Tag type for piecewise construction of std::pair objects.
Definition stl_pair.h:79