libstdc++
bits/alloc_traits.h
Go to the documentation of this file.
1// Allocator traits -*- C++ -*-
2
3// Copyright (C) 2011-2026 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 bits/alloc_traits.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 _ALLOC_TRAITS_H
31#define _ALLOC_TRAITS_H 1
32
33#include <bits/stl_construct.h>
34#include <bits/memoryfwd.h>
35#if __cplusplus >= 201103L
36# include <bits/ptr_traits.h>
37# include <ext/numeric_traits.h>
38# if _GLIBCXX_HOSTED
39# include <bits/allocator.h>
40# endif
41# if __cpp_exceptions
42# include <bits/stl_iterator.h> // __make_move_if_noexcept_iterator
43# endif
44#endif
45
46namespace std _GLIBCXX_VISIBILITY(default)
47{
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
49
50#if __cplusplus >= 201103L
51
52#pragma GCC diagnostic push
53#pragma GCC diagnostic ignored "-Wc++14-extensions" // for variable templates
54#pragma GCC diagnostic ignored "-Wc++17-extensions" // for if-constexpr
55
56 /// @cond undocumented
57 struct __allocator_traits_base
58 {
59#if __cpp_concepts
60 template<typename _Tp, typename _Up>
61#else
62 template<typename _Tp, typename _Up, typename = void>
63#endif
64 struct __rebind : __replace_first_arg<_Tp, _Up>
65 {
66 static_assert(is_same<
67 typename __replace_first_arg<_Tp, typename _Tp::value_type>::type,
68 _Tp>::value,
69 "allocator_traits<A>::rebind_alloc<A::value_type> must be A");
70 };
71
72 template<typename _Tp, typename _Up>
73#if __cpp_concepts
74 requires requires { typename _Tp::template rebind<_Up>::other; }
75 struct __rebind<_Tp, _Up>
76#else
77 struct __rebind<_Tp, _Up,
78 __void_t<typename _Tp::template rebind<_Up>::other>>
79#endif
80 {
81 using type = typename _Tp::template rebind<_Up>::other;
82
83 static_assert(is_same<
84 typename _Tp::template rebind<typename _Tp::value_type>::other,
85 _Tp>::value,
86 "allocator_traits<A>::rebind_alloc<A::value_type> must be A");
87 };
88
89 protected:
90 template<typename _Tp>
91 using __pointer = typename _Tp::pointer;
92 template<typename _Tp>
93 using __c_pointer = typename _Tp::const_pointer;
94 template<typename _Tp>
95 using __v_pointer = typename _Tp::void_pointer;
96 template<typename _Tp>
97 using __cv_pointer = typename _Tp::const_void_pointer;
98 template<typename _Tp>
99 using __pocca = typename _Tp::propagate_on_container_copy_assignment;
100 template<typename _Tp>
101 using __pocma = typename _Tp::propagate_on_container_move_assignment;
102 template<typename _Tp>
103 using __pocs = typename _Tp::propagate_on_container_swap;
104 template<typename _Tp>
105 using __equal = __type_identity<typename _Tp::is_always_equal>;
106
107 // __has_allocate_hint is true if a.allocate(n, hint) is well-formed.
108#if __cpp_concepts
109 template<typename _Alloc, typename _Sz, typename _Vp>
110 static constexpr bool __has_allocate_hint
111 = requires (_Alloc& __a, _Sz __n, _Vp __hint) {
112 __a.allocate(__n, __hint);
113 };
114#else
115 template<typename _Alloc, typename _Sz, typename _Vp>
116 using __allocate_hint_t
117 = decltype(std::declval<_Alloc&>()
118 .allocate(std::declval<_Sz>(), std::declval<_Vp>()));
119 template<typename _Alloc, typename _Sz, typename _Vp, typename = void>
120 static constexpr bool __has_allocate_hint = false;
121 template<typename _Alloc, typename _Sz, typename _Vp>
122 static constexpr bool
123 __has_allocate_hint<_Alloc, _Sz, _Vp,
124 __void_t<__allocate_hint_t<_Alloc, _Sz, _Vp>>>
125 = true;
126#endif
127
128 // __has_construct is true if a.construct(p, args...) is well-formed.
129 // __can_construct is true if either __has_construct is true, or if
130 // a placement new-expression for T(args...) is well-formed. We use this
131 // to constrain allocator_traits::construct, as a libstdc++ extension.
132#if __cpp_concepts
133 template<typename _Alloc, typename _Tp, typename... _Args>
134 static constexpr bool __has_construct
135 = requires (_Alloc& __a, _Tp* __p, _Args&&... __args) {
136 __a.construct(__p, std::forward<_Args>(__args)...);
137 };
138 template<typename _Tp, typename... _Args>
139 static constexpr bool __can_construct_at
140 = requires (_Tp* __p, _Args&&... __args) {
141#if __cpp_constexpr_dynamic_alloc
142 std::construct_at(__p, std::forward<_Args>(__args)...);
143#else
144 ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
145#endif
146 };
147 template<typename _Alloc, typename _Tp, typename... _Args>
148 static constexpr bool __can_construct
149 = __has_construct<_Alloc, _Tp, _Args...>
150 || __can_construct_at<_Tp, _Args...>;
151#else
152 template<typename _Alloc, typename _Tp, typename... _Args>
153 using __construct_t
154 = decltype(std::declval<_Alloc&>().construct(std::declval<_Tp*>(),
155 std::declval<_Args>()...));
156 template<typename _Alloc, typename _Tp, typename, typename... _Args>
157 static constexpr bool __has_construct_impl = false;
158 template<typename _Alloc, typename _Tp, typename... _Args>
159 static constexpr bool
160 __has_construct_impl<_Alloc, _Tp,
161 __void_t<__construct_t<_Alloc, _Tp, _Args...>>,
162 _Args...>
163 = true;
164 template<typename _Alloc, typename _Tp, typename... _Args>
165 static constexpr bool __has_construct
166 = __has_construct_impl<_Alloc, _Tp, void, _Args...>;
167 template<typename _Tp, typename... _Args>
168 using __new_expr_t
169 = decltype(::new((void*)0) _Tp(std::declval<_Args>()...));
170 template<typename _Tp, typename, typename... _Args>
171 static constexpr bool __has_new_expr = false;
172 template<typename _Tp, typename... _Args>
173 static constexpr bool
174 __has_new_expr<_Tp, __void_t<__new_expr_t<_Tp, _Args...>>, _Args...>
175 = true;
176 template<typename _Alloc, typename _Tp, typename... _Args>
177 static constexpr bool __can_construct
178 = __has_construct<_Alloc, _Tp, _Args...>
179 || __has_new_expr<_Tp, void, _Args...>;
180#endif
181
182 // __has_destroy is true if a.destroy(p) is well-formed.
183#if __cpp_concepts
184 template<typename _Alloc, typename _Tp>
185 static constexpr bool __has_destroy = requires (_Alloc& __a, _Tp* __p) {
186 __a.destroy(__p);
187 };
188#else
189 template<typename _Alloc, typename _Tp>
190 using __destroy_t
191 = decltype(std::declval<_Alloc&>().destroy(std::declval<_Tp*>()));
192 template<typename _Alloc, typename _Tp, typename = void>
193 static constexpr bool __has_destroy = false;
194 template<typename _Alloc, typename _Tp>
195 static constexpr bool __has_destroy<_Alloc, _Tp,
196 __void_t<__destroy_t<_Alloc, _Tp>>>
197 = true;
198#endif
199
200 // __has_max_size is true if a.max_size() is well-formed.
201#if __cpp_concepts
202 template<typename _Alloc>
203 static constexpr bool __has_max_size = requires (const _Alloc& __a) {
204 __a.max_size();
205 };
206#else
207 template<typename _Alloc>
208 using __max_size_t = decltype(std::declval<const _Alloc&>().max_size());
209 template<typename _Alloc, typename = void>
210 static constexpr bool __has_max_size = false;
211 template<typename _Alloc>
212 static constexpr bool __has_max_size<_Alloc,
213 __void_t<__max_size_t<_Alloc>>>
214 = true;
215#endif
216
217 // __has_soccc is true if a.select_on_container_copy_construction()
218 // is well-formed.
219#if __cpp_concepts
220 template<typename _Alloc>
221 static constexpr bool __has_soccc = requires (const _Alloc& __a) {
222 __a.select_on_container_copy_construction();
223 };
224#else
225 template<typename _Alloc>
226 using __soccc_t
227 = decltype(std::declval<const _Alloc&>()
228 .select_on_container_copy_construction());
229 template<typename _Alloc, typename = void>
230 static constexpr bool __has_soccc = false;
231 template<typename _Alloc>
232 static constexpr bool __has_soccc<_Alloc, __void_t<__soccc_t<_Alloc>>>
233 = true;
234#endif
235 };
236
237 template<typename _Alloc, typename _Up>
238 using __alloc_rebind
239 = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
240 /// @endcond
241
242#if __cplusplus > 202002L
243# define _GLIBCXX_NO_ALLOC_TRAITS_SPECIALIZATIONS _GLIBCXX_NO_SPECIALIZATIONS
244#else
245# define _GLIBCXX_NO_ALLOC_TRAITS_SPECIALIZATIONS
246#endif
247
248 /**
249 * @brief Uniform interface to all allocator types.
250 * @headerfile memory
251 * @ingroup allocators
252 * @since C++11
253 */
254 template<typename _Alloc>
255 struct _GLIBCXX_NO_ALLOC_TRAITS_SPECIALIZATIONS allocator_traits
256 : __allocator_traits_base
257 {
258 /// The allocator type
259 typedef _Alloc allocator_type;
260 /// The allocated type
261 typedef typename _Alloc::value_type value_type;
262
263 /**
264 * @brief The allocator's pointer type.
265 *
266 * @c Alloc::pointer if that type exists, otherwise @c value_type*
267 */
268 using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
269
270 private:
271 // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
272 template<template<typename> class _Func, typename _Tp, typename = void>
273 struct _Ptr
274 {
275 using type = typename pointer_traits<pointer>::template rebind<_Tp>;
276 };
277
278 template<template<typename> class _Func, typename _Tp>
279 struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
280 {
281 using type = _Func<_Alloc>;
282 };
283
284 // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
285 template<typename _A2, typename _PtrT, typename = void>
286 struct _Diff
287 { using type = typename pointer_traits<_PtrT>::difference_type; };
288
289 template<typename _A2, typename _PtrT>
290 struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
291 { using type = typename _A2::difference_type; };
292
293 // Select _A2::size_type or make_unsigned<_DiffT>::type
294 template<typename _A2, typename _DiffT, typename = void>
295 struct _Size : make_unsigned<_DiffT> { };
296
297 template<typename _A2, typename _DiffT>
298 struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
299 { using type = typename _A2::size_type; };
300
301 public:
302 /**
303 * @brief The allocator's const pointer type.
304 *
305 * @c Alloc::const_pointer if that type exists, otherwise
306 * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
307 */
308 using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
309
310 /**
311 * @brief The allocator's void pointer type.
312 *
313 * @c Alloc::void_pointer if that type exists, otherwise
314 * <tt> pointer_traits<pointer>::rebind<void> </tt>
315 */
316 using void_pointer = typename _Ptr<__v_pointer, void>::type;
317
318 /**
319 * @brief The allocator's const void pointer type.
320 *
321 * @c Alloc::const_void_pointer if that type exists, otherwise
322 * <tt> pointer_traits<pointer>::rebind<const void> </tt>
323 */
324 using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
325
326 /**
327 * @brief The allocator's difference type
328 *
329 * @c Alloc::difference_type if that type exists, otherwise
330 * <tt> pointer_traits<pointer>::difference_type </tt>
331 */
332 using difference_type = typename _Diff<_Alloc, pointer>::type;
333
334 /**
335 * @brief The allocator's size type
336 *
337 * @c Alloc::size_type if that type exists, otherwise
338 * <tt> make_unsigned<difference_type>::type </tt>
339 */
340 using size_type = typename _Size<_Alloc, difference_type>::type;
341
342 /**
343 * @brief How the allocator is propagated on copy assignment
344 *
345 * @c Alloc::propagate_on_container_copy_assignment if that type exists,
346 * otherwise @c false_type
347 */
349 = __detected_or_t<false_type, __pocca, _Alloc>;
350
351 /**
352 * @brief How the allocator is propagated on move assignment
353 *
354 * @c Alloc::propagate_on_container_move_assignment if that type exists,
355 * otherwise @c false_type
356 */
358 = __detected_or_t<false_type, __pocma, _Alloc>;
359
360 /**
361 * @brief How the allocator is propagated on swap
362 *
363 * @c Alloc::propagate_on_container_swap if that type exists,
364 * otherwise @c false_type
365 */
367 = __detected_or_t<false_type, __pocs, _Alloc>;
368
369 /**
370 * @brief Whether all instances of the allocator type compare equal.
371 *
372 * @c Alloc::is_always_equal if that type exists,
373 * otherwise @c is_empty<Alloc>::type
374 */
375 using is_always_equal
376 = typename __detected_or_t<is_empty<_Alloc>, __equal, _Alloc>::type;
377
378 template<typename _Tp>
379 using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
380 template<typename _Tp>
381 using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
382
383 /**
384 * @brief Allocate memory.
385 * @param __a An allocator.
386 * @param __n The number of objects to allocate space for.
388 * Calls @c a.allocate(n)
389 */
390 _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
391 allocate(_Alloc& __a, size_type __n)
392 { return __a.allocate(__n); }
393
394 /**
395 * @brief Allocate memory.
396 * @param __a An allocator.
397 * @param __n The number of objects to allocate space for.
398 * @param __hint Aid to locality.
399 * @return Memory of suitable size and alignment for @a n objects
400 * of type @c value_type
401 *
402 * Returns <tt> a.allocate(n, hint) </tt> if that expression is
403 * well-formed, otherwise returns @c a.allocate(n)
404 */
405 _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
406 allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
407 {
408 if constexpr (__has_allocate_hint<_Alloc, size_type, const_void_pointer>)
409 return __a.allocate(__n, __hint);
410 else
411 return __a.allocate(__n);
412 }
413
414#ifdef __glibcxx_allocate_at_least // C++23
415 /**
416 * @brief Allocate memory, generously.
417 * @param __a An allocator.
418 * @param __n The minimum number of objects to allocate space for.
419 * @return Memory of suitable size and alignment for `n` or more
420 * contiguous objects of type `value_type`.
421 *
422 * Returns `a.allocate_at_least(n)` if that expression is
423 * well-formed, else `{ a.allocate(n), n }`. When an allocator
424 * is obliged to reserve more space than required for the cited
425 * `n` objects, it may deliver the extra space to the caller.
426 */
427 [[nodiscard]] static constexpr allocation_result<pointer, size_type>
428 allocate_at_least(_Alloc& __a, size_type __n)
429 {
430 if constexpr (requires { __a.allocate_at_least(__n); })
431 return __a.allocate_at_least(__n);
432 else
433 return { __a.allocate(__n), __n };
434 }
435#endif
436
437 /**
438 * @brief Deallocate memory.
439 * @param __a An allocator.
440 * @param __p Pointer to the memory to deallocate.
441 * @param __n The number of objects space was allocated for.
443 * Calls <tt> a.deallocate(p, n) </tt>
444 */
445 static _GLIBCXX20_CONSTEXPR void
446 deallocate(_Alloc& __a, pointer __p, size_type __n)
447 { __a.deallocate(__p, __n); }
448
449 /**
450 * @brief Construct an object of type `_Tp`
451 * @param __a An allocator.
452 * @param __p Pointer to memory of suitable size and alignment for Tp
453 * @param __args Constructor arguments.
454 *
455 * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
456 * if that expression is well-formed, otherwise uses placement-new
457 * to construct an object of type @a _Tp at location @a __p from the
458 * arguments @a __args...
459 */
460 template<typename _Tp, typename... _Args>
461#if __cpp_concepts && __cpp_constexpr_dynamic_alloc
462 requires __can_construct<_Alloc, _Tp, _Args...>
463 static constexpr void
464#else
465 static __enable_if_t<__can_construct<_Alloc, _Tp, _Args...>>
466#endif
467 construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
468 noexcept(_S_nothrow_construct<_Tp, _Args...>())
469 {
470 if constexpr (__has_construct<_Alloc, _Tp, _Args...>)
471 __a.construct(__p, std::forward<_Args>(__args)...);
472 else
473 std::_Construct(__p, std::forward<_Args>(__args)...);
474 }
475
476 /**
477 * @brief Destroy an object of type @a _Tp
478 * @param __a An allocator.
479 * @param __p Pointer to the object to destroy
480 *
481 * Calls @c __a.destroy(__p) if that expression is well-formed,
482 * otherwise calls @c __p->~_Tp()
483 */
484 template<typename _Tp>
485 static _GLIBCXX20_CONSTEXPR void
486 destroy(_Alloc& __a, _Tp* __p)
487 noexcept(_S_nothrow_destroy<_Tp>())
488 {
489 if constexpr (__has_destroy<_Alloc, _Tp>)
490 __a.destroy(__p);
491 else
492 std::_Destroy(__p);
493 }
494
495 /**
496 * @brief The maximum supported allocation size
497 * @param __a An allocator.
498 * @return @c __a.max_size() or @c numeric_limits<size_type>::max()
499 *
500 * Returns @c __a.max_size() if that expression is well-formed,
501 * otherwise returns @c numeric_limits<size_type>::max()
502 */
503 static _GLIBCXX20_CONSTEXPR size_type
504 max_size(const _Alloc& __a) noexcept
505 {
506 if constexpr (__has_max_size<_Alloc>)
507 return __a.max_size();
508 else
509 // _GLIBCXX_RESOLVE_LIB_DEFECTS
510 // 2466. allocator_traits::max_size() default behavior is incorrect
511 return __gnu_cxx::__numeric_traits<size_type>::__max
512 / sizeof(value_type);
513 }
514
515 /**
516 * @brief Obtain an allocator to use when copying a container.
517 * @param __rhs An allocator.
518 * @return @c __rhs.select_on_container_copy_construction() or @a __rhs
519 *
520 * Returns @c __rhs.select_on_container_copy_construction() if that
521 * expression is well-formed, otherwise returns @a __rhs
522 */
523 static _GLIBCXX20_CONSTEXPR _Alloc
524 select_on_container_copy_construction(const _Alloc& __rhs)
525 {
526 if constexpr (__has_soccc<_Alloc>)
527 return __rhs.select_on_container_copy_construction();
528 else
529 return __rhs;
530 }
531
532 private:
533#if __cpp_constexpr >= 201304 // >= C++14
534 template<typename _Tp, typename... _Args>
535 static constexpr bool
536 _S_nothrow_construct(_Alloc* __a = nullptr, _Tp* __p = nullptr)
537 {
538 if constexpr (__has_construct<_Alloc, _Tp, _Args...>)
539 return noexcept(__a->construct(__p, std::declval<_Args>()...));
540 else
541 return __is_nothrow_new_constructible<_Tp, _Args...>;
542 }
543
544 template<typename _Tp>
545 static constexpr bool
546 _S_nothrow_destroy(_Alloc* __a = nullptr, _Tp* __p = nullptr)
547 {
548 if constexpr (__has_destroy<_Alloc, _Tp>)
549 return noexcept(__a->destroy(__p));
550 else
551 return is_nothrow_destructible<_Tp>::value;
552 }
553#else
554 template<typename _Tp, typename... _Args>
555 static constexpr
556 __enable_if_t<__has_construct<_Alloc, _Tp, _Args...>, bool>
557 _S_nothrow_construct(_Alloc* __a = nullptr, _Tp* __p = nullptr)
558 { return noexcept(__a->construct(__p, std::declval<_Args>()...)); }
559
560 template<typename _Tp, typename... _Args>
561 static constexpr
562 __enable_if_t<!__has_construct<_Alloc, _Tp, _Args...>, bool>
563 _S_nothrow_construct(_Alloc* = nullptr, _Tp* __p = nullptr)
564 { return __is_nothrow_new_constructible<_Tp, _Args...>; }
565
566 template<typename _Tp>
567 static constexpr
568 __enable_if_t<__has_destroy<_Alloc, _Tp>, bool>
569 _S_nothrow_destroy(_Alloc* __a = nullptr, _Tp* __p = nullptr)
570 { return noexcept(__a->destroy(__p)); }
571
572 template<typename _Tp>
573 static constexpr
574 __enable_if_t<!__has_destroy<_Alloc, _Tp>, bool>
575 _S_nothrow_destroy(_Alloc* = nullptr, _Tp* __p = nullptr)
576 { return is_nothrow_destructible<_Tp>::value; }
577#endif
578 };
579#pragma GCC diagnostic pop
580
581#undef _GLIBCXX_NO_ALLOC_TRAITS_SPECIALIZATIONS
582
583#if _GLIBCXX_HOSTED
584#pragma GCC diagnostic push
585#pragma GCC diagnostic ignored "-Winvalid-specialization"
586
587 /**
588 * @brief Partial specialization for `std::allocator`
589 * @headerfile memory
590 * @ingroup allocators
591 * @since C++11
592 * @see std::allocator_traits
593 */
594 template<typename _Tp>
596 {
597 /// The allocator type
599
600 /// The allocated type
601 using value_type = _Tp;
602
603 /// The allocator's pointer type.
604 using pointer = _Tp*;
605
606 /// The allocator's const pointer type.
607 using const_pointer = const _Tp*;
608
609 /// The allocator's void pointer type.
610 using void_pointer = void*;
611
612 /// The allocator's const void pointer type.
613 using const_void_pointer = const void*;
614
615 /// The allocator's difference type
616 using difference_type = std::ptrdiff_t;
617
618 /// The allocator's size type
619 using size_type = std::size_t;
620
621 /// How the allocator is propagated on copy assignment
623
624 /// How the allocator is propagated on move assignment
626
627 /// How the allocator is propagated on swap
629
630 /// Whether all instances of the allocator type compare equal.
632
633 template<typename _Up>
634 using rebind_alloc = allocator<_Up>;
635
636 template<typename _Up>
637 using rebind_traits = allocator_traits<allocator<_Up>>;
638
639 /**
640 * @brief Allocate memory.
641 * @param __a An allocator.
642 * @param __n The number of objects to allocate space for.
643 *
644 * Calls @c a.allocate(n)
645 */
646 [[__nodiscard__,__gnu__::__always_inline__]]
647 static _GLIBCXX20_CONSTEXPR pointer
649 { return __a.allocate(__n); }
650
651 /**
652 * @brief Allocate memory.
653 * @param __a An allocator.
654 * @param __n The number of objects to allocate space for.
655 * @param __hint Aid to locality.
656 * @return Memory of suitable size and alignment for @a n objects
657 * of type @c value_type
658 *
659 * Returns <tt> a.allocate(n, hint) </tt>
660 */
661 [[__nodiscard__,__gnu__::__always_inline__]]
662 static _GLIBCXX20_CONSTEXPR pointer
664 [[maybe_unused]] const_void_pointer __hint)
665 {
666#if __cplusplus <= 201703L
667 return __a.allocate(__n, __hint);
668#else
669 return __a.allocate(__n);
670#endif
671 }
672
673#ifdef __glibcxx_allocate_at_least // C++23
674 /**
675 * @brief Allocate memory, generously.
676 * @param __a An allocator.
677 * @param __n The minimum number of objects to allocate space for.
678 * @return Memory of suitable size and alignment for `m >= n`
679 * contiguous objects of type `value_type`, and `m`.
680 *
681 * Returns `a.allocate_at_least(n)`.
682 */
683 [[nodiscard,__gnu__::__always_inline__]]
684 static constexpr allocation_result<pointer, size_type>
686 { return __a.allocate_at_least(__n); }
687#endif
688
689 /**
690 * @brief Deallocate memory.
691 * @param __a An allocator.
692 * @param __p Pointer to the memory to deallocate.
693 * @param __n The number of objects space was allocated for.
694 *
695 * Calls <tt> a.deallocate(p, n) </tt>
696 */
697 [[__gnu__::__always_inline__]]
698 static _GLIBCXX20_CONSTEXPR void
700 { __a.deallocate(__p, __n); }
701
702 /**
703 * @brief Construct an object of type `_Up`
704 * @param __a An allocator.
705 * @param __p Pointer to memory of suitable size and alignment for
706 * an object of type `_Up`.
707 * @param __args Constructor arguments.
708 *
709 * Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
710 * in C++11, C++14 and C++17. Changed in C++20 to call
711 * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
712 */
713 template<typename _Up, typename... _Args>
714 [[__gnu__::__always_inline__]]
715 static _GLIBCXX20_CONSTEXPR void
716 construct(allocator_type& __a __attribute__((__unused__)),
717 _Up* __p, _Args&&... __args)
718#if __cplusplus <= 201703L
719 noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
720#else
721 noexcept(__is_nothrow_new_constructible<_Up, _Args...>)
722#endif
723 {
724#if __cplusplus <= 201703L
725 __a.construct(__p, std::forward<_Args>(__args)...);
726#elif __cpp_constexpr_dynamic_alloc // >= C++20
727 std::construct_at(__p, std::forward<_Args>(__args)...);
728#else
729 std::_Construct(__p, std::forward<_Args>(__args)...);
730#endif
731 }
732
733 /**
734 * @brief Destroy an object of type @a _Up
735 * @param __a An allocator.
736 * @param __p Pointer to the object to destroy
737 *
738 * Calls @c __a.destroy(__p).
739 */
740 template<typename _Up>
741 [[__gnu__::__always_inline__]]
742 static _GLIBCXX20_CONSTEXPR void
743 destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p)
745 {
746#if __cplusplus <= 201703L
747 __a.destroy(__p);
748#else
749 std::destroy_at(__p);
750#endif
751 }
752
753 /**
754 * @brief The maximum supported allocation size
755 * @param __a An allocator.
756 * @return @c __a.max_size()
757 */
758 [[__gnu__::__always_inline__]]
759 static _GLIBCXX20_CONSTEXPR size_type
760 max_size(const allocator_type& __a __attribute__((__unused__))) noexcept
761 {
762#if __cplusplus <= 201703L
763 return __a.max_size();
764#else
765 return size_t(-1) / sizeof(value_type);
766#endif
767 }
768
769 /**
770 * @brief Obtain an allocator to use when copying a container.
771 * @param __rhs An allocator.
772 * @return @c __rhs
773 */
774 [[__gnu__::__always_inline__]]
775 static _GLIBCXX20_CONSTEXPR allocator_type
777 { return __rhs; }
778 };
779
780 /**
781 * @brief Explicit specialization for `std::allocator<void>`
782 * @headerfile memory
783 * @ingroup allocators
784 * @since C++11
785 * @see std::allocator_traits
786 */
787 template<>
789 {
790 /// The allocator type
792
793 /// The allocated type
794 using value_type = void;
795
796 /// The allocator's pointer type.
797 using pointer = void*;
798
799 /// The allocator's const pointer type.
800 using const_pointer = const void*;
801
802 /// The allocator's void pointer type.
803 using void_pointer = void*;
804
805 /// The allocator's const void pointer type.
806 using const_void_pointer = const void*;
807
808 /// The allocator's difference type
809 using difference_type = std::ptrdiff_t;
810
811 /// The allocator's size type
812 using size_type = std::size_t;
813
814 /// How the allocator is propagated on copy assignment
816
817 /// How the allocator is propagated on move assignment
819
820 /// How the allocator is propagated on swap
822
823 /// Whether all instances of the allocator type compare equal.
825
826 template<typename _Up>
827 using rebind_alloc = allocator<_Up>;
828
829 template<typename _Up>
830 using rebind_traits = allocator_traits<allocator<_Up>>;
831
832 /// allocate is ill-formed for allocator<void>
833 static void*
834 allocate(allocator_type&, size_type, const void* = nullptr) = delete;
835
836#ifdef __glibcxx_allocate_at_least
837 static allocation_result<void*, size_type>
839#endif
840
841 /// deallocate is ill-formed for allocator<void>
842 static void
844
845 /**
846 * @brief Construct an object of type `_Up`
847 * @param __a An allocator.
848 * @param __p Pointer to memory of suitable size and alignment for
849 * an object of type `_Up`.
850 * @param __args Constructor arguments.
851 *
852 * Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
853 * in C++11, C++14 and C++17. Changed in C++20 to call
854 * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
855 */
856 template<typename _Up, typename... _Args>
857 [[__gnu__::__always_inline__]]
858 static _GLIBCXX20_CONSTEXPR void
859 construct(allocator_type&, _Up* __p, _Args&&... __args)
860 noexcept(__is_nothrow_new_constructible<_Up, _Args...>)
861 { std::_Construct(__p, std::forward<_Args>(__args)...); }
862
863 /**
864 * @brief Destroy an object of type `_Up`
865 * @param __a An allocator.
866 * @param __p Pointer to the object to destroy
867 *
868 * Invokes the destructor for `*__p`.
869 */
870 template<typename _Up>
871 [[__gnu__::__always_inline__]]
872 static _GLIBCXX20_CONSTEXPR void
876
877 /// max_size is ill-formed for allocator<void>
878 static size_type
879 max_size(const allocator_type&) = delete;
880
881 /**
882 * @brief Obtain an allocator to use when copying a container.
883 * @param __rhs An allocator.
884 * @return `__rhs`
885 */
886 [[__gnu__::__always_inline__]]
887 static _GLIBCXX20_CONSTEXPR allocator_type
889 { return __rhs; }
890 };
891#pragma GCC diagnostic pop
892#endif // _GLIBCXX_HOSTED
893
894 /// @cond undocumented
895#pragma GCC diagnostic push
896#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
897 template<typename _Alloc>
898 [[__gnu__::__always_inline__]]
899 _GLIBCXX14_CONSTEXPR inline void
900 __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
901 {
902 using __traits = allocator_traits<_Alloc>;
903 using __pocca =
904 typename __traits::propagate_on_container_copy_assignment::type;
905 if constexpr (__pocca::value)
906 __one = __two;
907 }
908
909 template<typename _Alloc>
910 [[__gnu__::__always_inline__]]
911 constexpr _Alloc
912 __alloc_on_copy(const _Alloc& __a)
913 {
914 typedef allocator_traits<_Alloc> __traits;
915 return __traits::select_on_container_copy_construction(__a);
916 }
917
918 template<typename _Alloc>
919 [[__gnu__::__always_inline__]]
920 _GLIBCXX14_CONSTEXPR inline void
921 __alloc_on_move(_Alloc& __one, _Alloc& __two)
922 {
923 using __traits = allocator_traits<_Alloc>;
924 using __pocma
925 = typename __traits::propagate_on_container_move_assignment::type;
926 if constexpr (__pocma::value)
927 __one = std::move(__two);
928 }
929
930 template<typename _Alloc>
931 [[__gnu__::__always_inline__]]
932 _GLIBCXX14_CONSTEXPR inline void
933 __alloc_on_swap(_Alloc& __one, _Alloc& __two)
934 {
935 using __traits = allocator_traits<_Alloc>;
936 using __pocs = typename __traits::propagate_on_container_swap::type;
937 if constexpr (__pocs::value)
938 {
939 using std::swap;
940 swap(__one, __two);
941 }
942 }
943#pragma GCC diagnostic pop
944
945 template<typename _Alloc, typename _Tp,
946 typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
947 typename = void>
948 struct __is_alloc_insertable_impl
949 : false_type
950 { };
951
952 template<typename _Alloc, typename _Tp, typename _ValueT>
953 struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
954 __void_t<decltype(allocator_traits<_Alloc>::construct(
955 std::declval<_Alloc&>(), std::declval<_ValueT*>(),
956 std::declval<_Tp>()))>>
957 : true_type
958 { };
959
960 // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
961 // (might be wrong if _Alloc::construct exists but is not constrained,
962 // i.e. actually trying to use it would still be invalid. Use with caution.)
963 template<typename _Alloc>
964 struct __is_copy_insertable
965 : __is_alloc_insertable_impl<_Alloc,
966 typename _Alloc::value_type const&>::type
967 { };
968
969#if _GLIBCXX_HOSTED
970 // std::allocator<_Tp> just requires CopyConstructible
971 template<typename _Tp>
972 struct __is_copy_insertable<allocator<_Tp>>
974 { };
975#endif
976
977 // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
978 // (might be wrong if _Alloc::construct exists but is not constrained,
979 // i.e. actually trying to use it would still be invalid. Use with caution.)
980 template<typename _Alloc>
981 struct __is_move_insertable
982 : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
983 { };
984
985#if _GLIBCXX_HOSTED
986 // std::allocator<_Tp> just requires MoveConstructible
987 template<typename _Tp>
988 struct __is_move_insertable<allocator<_Tp>>
990 { };
991#endif
992
993 // Trait to detect Allocator-like types.
994 template<typename _Alloc, typename = void>
995 struct __is_allocator : false_type { };
996
997 template<typename _Alloc>
998 struct __is_allocator<_Alloc,
999 __void_t<typename _Alloc::value_type,
1000 decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
1001 : true_type { };
1002
1003 template<typename _Alloc>
1004 using _RequireAllocator
1005 = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
1006
1007 template<typename _Alloc>
1008 using _RequireNotAllocator
1009 = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
1010
1011#if __cpp_concepts >= 201907L
1012 template<typename _Alloc>
1013 concept __allocator_like = requires (_Alloc& __a) {
1014 typename _Alloc::value_type;
1015 __a.deallocate(__a.allocate(1u), 1u);
1016 };
1017
1018 template<typename _Alloc>
1019 concept __not_allocator_like = !__allocator_like<_Alloc>;
1020#endif
1021 /// @endcond
1022#endif // C++11
1023
1024 /// @cond undocumented
1025
1026 // To implement Option 3 of DR 431.
1027 template<typename _Alloc, bool = __is_empty(_Alloc)>
1028 struct __alloc_swap
1029 { static void _S_do_it(_Alloc&, _Alloc&) _GLIBCXX_NOEXCEPT { } };
1030
1031 template<typename _Alloc>
1032 struct __alloc_swap<_Alloc, false>
1033 {
1034 static void
1035 _S_do_it(_Alloc& __one, _Alloc& __two) _GLIBCXX_NOEXCEPT
1036 {
1037 // Precondition: swappable allocators.
1038 if (__one != __two)
1039 swap(__one, __two);
1040 }
1041 };
1042
1043#if __cplusplus >= 201103L
1044 template<typename _Tp, bool
1045 = __or_<is_copy_constructible<typename _Tp::value_type>,
1047 struct __shrink_to_fit_aux
1048 { static bool _S_do_it(_Tp&) noexcept { return false; } };
1049
1050 template<typename _Tp>
1051 struct __shrink_to_fit_aux<_Tp, true>
1052 {
1053 _GLIBCXX20_CONSTEXPR
1054 static bool
1055 _S_do_it(_Tp& __c) noexcept
1056 {
1057#if __cpp_exceptions
1058 try
1059 {
1060 _Tp(__make_move_if_noexcept_iterator(__c.begin()),
1061 __make_move_if_noexcept_iterator(__c.end()),
1062 __c.get_allocator()).swap(__c);
1063 return true;
1064 }
1065 catch(...)
1066 { return false; }
1067#else
1068 return false;
1069#endif
1070 }
1071 };
1072#endif
1073
1074 /**
1075 * Destroy a range of objects using the supplied allocator. For
1076 * non-default allocators we do not optimize away invocation of
1077 * destroy() even if _Tp has a trivial destructor.
1078 */
1079
1080 template<typename _ForwardIterator, typename _Allocator>
1081 _GLIBCXX20_CONSTEXPR
1082 void
1083 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
1084 _Allocator& __alloc)
1085 {
1086 for (; __first != __last; ++__first)
1087#if __cplusplus < 201103L
1088 __alloc.destroy(std::__addressof(*__first));
1089#else
1091 std::__addressof(*__first));
1092#endif
1093 }
1094
1095#if _GLIBCXX_HOSTED
1096 template<typename _ForwardIterator, typename _Tp>
1097 __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR
1098 inline void
1099 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
1101 {
1102 std::_Destroy(__first, __last);
1103 }
1104#endif
1105
1106 /// @endcond
1107
1108_GLIBCXX_END_NAMESPACE_VERSION
1109} // namespace std
1110#endif // _ALLOC_TRAITS_H
__bool_constant< true > true_type
The type used as a compile-time boolean with true value.
Definition type_traits:119
__bool_constant< false > false_type
The type used as a compile-time boolean with false value.
Definition type_traits:122
auto declval() noexcept -> decltype(__declval< _Tp >(0))
Definition type_traits:2741
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:138
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition move.h:52
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.
constexpr void _Construct(_Tp *__p, _Args &&... __args)
constexpr void _Destroy(_ForwardIterator __first, _ForwardIterator __last)
Define a member typedef type only if a boolean constant is true.
Definition type_traits:137
is_nothrow_destructible
Definition type_traits:1198
is_copy_constructible
Definition type_traits:1301
is_move_constructible
Definition type_traits:1328
is_nothrow_move_constructible
Definition type_traits:1370
Uniform interface to all allocator types.
__detected_or_t< false_type, __pocma, _OuterAlloc > propagate_on_container_move_assignment
typename _Ptr< __v_pointer, void >::type void_pointer
__detected_or_t< value_type *, __pointer, _OuterAlloc > pointer
static constexpr void construct(_OuterAlloc &__a, _Tp *__p, _Args &&... __args) noexcept(_S_nothrow_construct< _Tp, _Args... >())
static constexpr pointer allocate(_OuterAlloc &__a, size_type __n)
typename _Size< _OuterAlloc, difference_type >::type size_type
typename _Ptr< __cv_pointer, const void >::type const_void_pointer
static constexpr allocation_result< pointer, size_type > allocate_at_least(_OuterAlloc &__a, size_type __n)
static constexpr void destroy(_OuterAlloc &__a, _Tp *__p) noexcept(_S_nothrow_destroy< _Tp >())
typename _Diff< _OuterAlloc, pointer >::type difference_type
typename _Ptr< __c_pointer, const value_type >::type const_pointer
static constexpr void deallocate(_OuterAlloc &__a, pointer __p, size_type __n)
typename __detected_or_t< is_empty< _OuterAlloc >, __equal, _OuterAlloc >::type is_always_equal
static constexpr size_type max_size(const _OuterAlloc &__a) noexcept
__detected_or_t< false_type, __pocca, _OuterAlloc > propagate_on_container_copy_assignment
static constexpr _OuterAlloc select_on_container_copy_construction(const _OuterAlloc &__rhs)
__detected_or_t< false_type, __pocs, _OuterAlloc > propagate_on_container_swap
allocator< _Tp > allocator_type
The allocator type.
static constexpr void construct(allocator_type &__a, _Up *__p, _Args &&... __args) noexcept(__is_nothrow_new_constructible< _Up, _Args... >)
Construct an object of type _Up.
void * void_pointer
The allocator's void pointer type.
_Tp * pointer
The allocator's pointer type.
false_type propagate_on_container_swap
How the allocator is propagated on swap.
static constexpr pointer allocate(allocator_type &__a, size_type __n)
Allocate memory.
static constexpr pointer allocate(allocator_type &__a, size_type __n, const_void_pointer __hint)
Allocate memory.
std::ptrdiff_t difference_type
The allocator's difference type.
true_type is_always_equal
Whether all instances of the allocator type compare equal.
const _Tp * const_pointer
The allocator's const pointer type.
static constexpr allocation_result< pointer, size_type > allocate_at_least(allocator_type &__a, size_type __n)
Allocate memory, generously.
const void * const_void_pointer
The allocator's const void pointer type.
true_type propagate_on_container_move_assignment
How the allocator is propagated on move assignment.
static constexpr void deallocate(allocator_type &__a, pointer __p, size_type __n)
Deallocate memory.
static constexpr size_type max_size(const allocator_type &__a) noexcept
The maximum supported allocation size.
static constexpr allocator_type select_on_container_copy_construction(const allocator_type &__rhs)
Obtain an allocator to use when copying a container.
static constexpr void destroy(allocator_type &__a, _Up *__p) noexcept(is_nothrow_destructible< _Up >::value)
Destroy an object of type _Up.
false_type propagate_on_container_copy_assignment
How the allocator is propagated on copy assignment.
std::size_t size_type
The allocator's size type.
false_type propagate_on_container_copy_assignment
How the allocator is propagated on copy assignment.
void * pointer
The allocator's pointer type.
void * void_pointer
The allocator's void pointer type.
static void deallocate(allocator_type &, void *, size_type)=delete
deallocate is ill-formed for allocator<void>
allocator< void > allocator_type
The allocator type.
true_type is_always_equal
Whether all instances of the allocator type compare equal.
static size_type max_size(const allocator_type &)=delete
max_size is ill-formed for allocator<void>
std::size_t size_type
The allocator's size type.
true_type propagate_on_container_move_assignment
How the allocator is propagated on move assignment.
const void * const_pointer
The allocator's const pointer type.
std::ptrdiff_t difference_type
The allocator's difference type.
static void * allocate(allocator_type &, size_type, const void *=nullptr)=delete
allocate is ill-formed for allocator<void>
static constexpr allocator_type select_on_container_copy_construction(const allocator_type &__rhs)
Obtain an allocator to use when copying a container.
static constexpr void construct(allocator_type &, _Up *__p, _Args &&... __args) noexcept(__is_nothrow_new_constructible< _Up, _Args... >)
Construct an object of type _Up.
const void * const_void_pointer
The allocator's const void pointer type.
static constexpr void destroy(allocator_type &, _Up *__p) noexcept(is_nothrow_destructible< _Up >::value)
Destroy an object of type _Up.
false_type propagate_on_container_swap
How the allocator is propagated on swap.
The standard allocator, as per C++03 [20.4.1].
Definition allocator.h:134
Uniform interface to all pointer-like types.
Definition ptr_traits.h:180