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