libstdc++
bits/alloc_traits.h
Go to the documentation of this file.
1 // Allocator traits -*- C++ -*-
2 
3 // Copyright (C) 2011-2022 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/allocator.h>
37 # include <bits/ptr_traits.h>
38 # include <ext/numeric_traits.h>
39 #endif
40 
41 namespace std _GLIBCXX_VISIBILITY(default)
42 {
43 _GLIBCXX_BEGIN_NAMESPACE_VERSION
44 
45 #if __cplusplus >= 201103L
46 #define __cpp_lib_allocator_traits_is_always_equal 201411L
47 
48  /// @cond undocumented
49  struct __allocator_traits_base
50  {
51  template<typename _Tp, typename _Up, typename = void>
52  struct __rebind : __replace_first_arg<_Tp, _Up> { };
53 
54  template<typename _Tp, typename _Up>
55  struct __rebind<_Tp, _Up,
56  __void_t<typename _Tp::template rebind<_Up>::other>>
57  { using type = typename _Tp::template rebind<_Up>::other; };
58 
59  protected:
60  template<typename _Tp>
61  using __pointer = typename _Tp::pointer;
62  template<typename _Tp>
63  using __c_pointer = typename _Tp::const_pointer;
64  template<typename _Tp>
65  using __v_pointer = typename _Tp::void_pointer;
66  template<typename _Tp>
67  using __cv_pointer = typename _Tp::const_void_pointer;
68  template<typename _Tp>
69  using __pocca = typename _Tp::propagate_on_container_copy_assignment;
70  template<typename _Tp>
71  using __pocma = typename _Tp::propagate_on_container_move_assignment;
72  template<typename _Tp>
73  using __pocs = typename _Tp::propagate_on_container_swap;
74  template<typename _Tp>
75  using __equal = __type_identity<typename _Tp::is_always_equal>;
76  };
77 
78  template<typename _Alloc, typename _Up>
79  using __alloc_rebind
80  = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
81  /// @endcond
82 
83  /**
84  * @brief Uniform interface to all allocator types.
85  * @headerfile memory
86  * @ingroup allocators
87  * @since C++11
88  */
89  template<typename _Alloc>
90  struct allocator_traits : __allocator_traits_base
91  {
92  /// The allocator type
93  typedef _Alloc allocator_type;
94  /// The allocated type
95  typedef typename _Alloc::value_type value_type;
96 
97  /**
98  * @brief The allocator's pointer type.
99  *
100  * @c Alloc::pointer if that type exists, otherwise @c value_type*
101  */
102  using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
103 
104  private:
105  // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
106  template<template<typename> class _Func, typename _Tp, typename = void>
107  struct _Ptr
108  {
109  using type = typename pointer_traits<pointer>::template rebind<_Tp>;
110  };
111 
112  template<template<typename> class _Func, typename _Tp>
113  struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
114  {
115  using type = _Func<_Alloc>;
116  };
117 
118  // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
119  template<typename _A2, typename _PtrT, typename = void>
120  struct _Diff
121  { using type = typename pointer_traits<_PtrT>::difference_type; };
122 
123  template<typename _A2, typename _PtrT>
124  struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
125  { using type = typename _A2::difference_type; };
126 
127  // Select _A2::size_type or make_unsigned<_DiffT>::type
128  template<typename _A2, typename _DiffT, typename = void>
129  struct _Size : make_unsigned<_DiffT> { };
130 
131  template<typename _A2, typename _DiffT>
132  struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
133  { using type = typename _A2::size_type; };
134 
135  public:
136  /**
137  * @brief The allocator's const pointer type.
138  *
139  * @c Alloc::const_pointer if that type exists, otherwise
140  * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
141  */
142  using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
143 
144  /**
145  * @brief The allocator's void pointer type.
146  *
147  * @c Alloc::void_pointer if that type exists, otherwise
148  * <tt> pointer_traits<pointer>::rebind<void> </tt>
149  */
150  using void_pointer = typename _Ptr<__v_pointer, void>::type;
151 
152  /**
153  * @brief The allocator's const void pointer type.
154  *
155  * @c Alloc::const_void_pointer if that type exists, otherwise
156  * <tt> pointer_traits<pointer>::rebind<const void> </tt>
157  */
158  using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
159 
160  /**
161  * @brief The allocator's difference type
162  *
163  * @c Alloc::difference_type if that type exists, otherwise
164  * <tt> pointer_traits<pointer>::difference_type </tt>
165  */
166  using difference_type = typename _Diff<_Alloc, pointer>::type;
167 
168  /**
169  * @brief The allocator's size type
170  *
171  * @c Alloc::size_type if that type exists, otherwise
172  * <tt> make_unsigned<difference_type>::type </tt>
173  */
174  using size_type = typename _Size<_Alloc, difference_type>::type;
175 
176  /**
177  * @brief How the allocator is propagated on copy assignment
178  *
179  * @c Alloc::propagate_on_container_copy_assignment if that type exists,
180  * otherwise @c false_type
181  */
183  = __detected_or_t<false_type, __pocca, _Alloc>;
184 
185  /**
186  * @brief How the allocator is propagated on move assignment
187  *
188  * @c Alloc::propagate_on_container_move_assignment if that type exists,
189  * otherwise @c false_type
190  */
192  = __detected_or_t<false_type, __pocma, _Alloc>;
193 
194  /**
195  * @brief How the allocator is propagated on swap
196  *
197  * @c Alloc::propagate_on_container_swap if that type exists,
198  * otherwise @c false_type
199  */
201  = __detected_or_t<false_type, __pocs, _Alloc>;
202 
203  /**
204  * @brief Whether all instances of the allocator type compare equal.
205  *
206  * @c Alloc::is_always_equal if that type exists,
207  * otherwise @c is_empty<Alloc>::type
208  */
209  using is_always_equal
210  = typename __detected_or_t<is_empty<_Alloc>, __equal, _Alloc>::type;
211 
212  template<typename _Tp>
213  using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
214  template<typename _Tp>
216 
217  private:
218  template<typename _Alloc2>
219  static constexpr auto
220  _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
221  -> decltype(__a.allocate(__n, __hint))
222  { return __a.allocate(__n, __hint); }
223 
224  template<typename _Alloc2>
225  static constexpr pointer
226  _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
227  { return __a.allocate(__n); }
228 
229  template<typename _Tp, typename... _Args>
230  struct __construct_helper
231  {
232  template<typename _Alloc2,
233  typename = decltype(std::declval<_Alloc2*>()->construct(
234  std::declval<_Tp*>(), std::declval<_Args>()...))>
235  static true_type __test(int);
236 
237  template<typename>
238  static false_type __test(...);
239 
240  using type = decltype(__test<_Alloc>(0));
241  };
242 
243  template<typename _Tp, typename... _Args>
244  using __has_construct
245  = typename __construct_helper<_Tp, _Args...>::type;
246 
247  template<typename _Tp, typename... _Args>
248  static _GLIBCXX14_CONSTEXPR _Require<__has_construct<_Tp, _Args...>>
249  _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
250  noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
251  { __a.construct(__p, std::forward<_Args>(__args)...); }
252 
253  template<typename _Tp, typename... _Args>
254  static _GLIBCXX14_CONSTEXPR
255  _Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
256  is_constructible<_Tp, _Args...>>>
257  _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
259  {
260 #if __cplusplus <= 201703L
261  ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
262 #else
263  std::construct_at(__p, std::forward<_Args>(__args)...);
264 #endif
265  }
266 
267  template<typename _Alloc2, typename _Tp>
268  static _GLIBCXX14_CONSTEXPR auto
269  _S_destroy(_Alloc2& __a, _Tp* __p, int)
270  noexcept(noexcept(__a.destroy(__p)))
271  -> decltype(__a.destroy(__p))
272  { __a.destroy(__p); }
273 
274  template<typename _Alloc2, typename _Tp>
275  static _GLIBCXX14_CONSTEXPR void
276  _S_destroy(_Alloc2&, _Tp* __p, ...)
278  { std::_Destroy(__p); }
279 
280  template<typename _Alloc2>
281  static constexpr auto
282  _S_max_size(_Alloc2& __a, int)
283  -> decltype(__a.max_size())
284  { return __a.max_size(); }
285 
286  template<typename _Alloc2>
287  static constexpr size_type
288  _S_max_size(_Alloc2&, ...)
289  {
290  // _GLIBCXX_RESOLVE_LIB_DEFECTS
291  // 2466. allocator_traits::max_size() default behavior is incorrect
292  return __gnu_cxx::__numeric_traits<size_type>::__max
293  / sizeof(value_type);
294  }
295 
296  template<typename _Alloc2>
297  static constexpr auto
298  _S_select(_Alloc2& __a, int)
299  -> decltype(__a.select_on_container_copy_construction())
300  { return __a.select_on_container_copy_construction(); }
301 
302  template<typename _Alloc2>
303  static constexpr _Alloc2
304  _S_select(_Alloc2& __a, ...)
305  { return __a; }
306 
307  public:
308 
309  /**
310  * @brief Allocate memory.
311  * @param __a An allocator.
312  * @param __n The number of objects to allocate space for.
313  *
314  * Calls @c a.allocate(n)
315  */
316  _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
317  allocate(_Alloc& __a, size_type __n)
318  { return __a.allocate(__n); }
319 
320  /**
321  * @brief Allocate memory.
322  * @param __a An allocator.
323  * @param __n The number of objects to allocate space for.
324  * @param __hint Aid to locality.
325  * @return Memory of suitable size and alignment for @a n objects
326  * of type @c value_type
327  *
328  * Returns <tt> a.allocate(n, hint) </tt> if that expression is
329  * well-formed, otherwise returns @c a.allocate(n)
330  */
331  _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
332  allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
333  { return _S_allocate(__a, __n, __hint, 0); }
334 
335  /**
336  * @brief Deallocate memory.
337  * @param __a An allocator.
338  * @param __p Pointer to the memory to deallocate.
339  * @param __n The number of objects space was allocated for.
340  *
341  * Calls <tt> a.deallocate(p, n) </tt>
342  */
343  static _GLIBCXX20_CONSTEXPR void
344  deallocate(_Alloc& __a, pointer __p, size_type __n)
345  { __a.deallocate(__p, __n); }
346 
347  /**
348  * @brief Construct an object of type `_Tp`
349  * @param __a An allocator.
350  * @param __p Pointer to memory of suitable size and alignment for Tp
351  * @param __args Constructor arguments.
352  *
353  * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
354  * if that expression is well-formed, otherwise uses placement-new
355  * to construct an object of type @a _Tp at location @a __p from the
356  * arguments @a __args...
357  */
358  template<typename _Tp, typename... _Args>
359  static _GLIBCXX20_CONSTEXPR auto
360  construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
361  noexcept(noexcept(_S_construct(__a, __p,
362  std::forward<_Args>(__args)...)))
363  -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
364  { _S_construct(__a, __p, std::forward<_Args>(__args)...); }
365 
366  /**
367  * @brief Destroy an object of type @a _Tp
368  * @param __a An allocator.
369  * @param __p Pointer to the object to destroy
370  *
371  * Calls @c __a.destroy(__p) if that expression is well-formed,
372  * otherwise calls @c __p->~_Tp()
373  */
374  template<typename _Tp>
375  static _GLIBCXX20_CONSTEXPR void
376  destroy(_Alloc& __a, _Tp* __p)
377  noexcept(noexcept(_S_destroy(__a, __p, 0)))
378  { _S_destroy(__a, __p, 0); }
379 
380  /**
381  * @brief The maximum supported allocation size
382  * @param __a An allocator.
383  * @return @c __a.max_size() or @c numeric_limits<size_type>::max()
384  *
385  * Returns @c __a.max_size() if that expression is well-formed,
386  * otherwise returns @c numeric_limits<size_type>::max()
387  */
388  static _GLIBCXX20_CONSTEXPR size_type
389  max_size(const _Alloc& __a) noexcept
390  { return _S_max_size(__a, 0); }
391 
392  /**
393  * @brief Obtain an allocator to use when copying a container.
394  * @param __rhs An allocator.
395  * @return @c __rhs.select_on_container_copy_construction() or @a __rhs
396  *
397  * Returns @c __rhs.select_on_container_copy_construction() if that
398  * expression is well-formed, otherwise returns @a __rhs
399  */
400  static _GLIBCXX20_CONSTEXPR _Alloc
402  { return _S_select(__rhs, 0); }
403  };
404 
405 #if __cplusplus > 201703L
406 # define __cpp_lib_constexpr_dynamic_alloc 201907L
407 #endif
408 
409  /// Partial specialization for std::allocator.
410  template<typename _Tp>
412  {
413  /// The allocator type
414  using allocator_type = allocator<_Tp>;
415 
416  /// The allocated type
417  using value_type = _Tp;
418 
419  /// The allocator's pointer type.
420  using pointer = _Tp*;
421 
422  /// The allocator's const pointer type.
423  using const_pointer = const _Tp*;
424 
425  /// The allocator's void pointer type.
426  using void_pointer = void*;
427 
428  /// The allocator's const void pointer type.
429  using const_void_pointer = const void*;
430 
431  /// The allocator's difference type
432  using difference_type = std::ptrdiff_t;
433 
434  /// The allocator's size type
435  using size_type = std::size_t;
436 
437  /// How the allocator is propagated on copy assignment
439 
440  /// How the allocator is propagated on move assignment
442 
443  /// How the allocator is propagated on swap
445 
446  /// Whether all instances of the allocator type compare equal.
448 
449  template<typename _Up>
451 
452  template<typename _Up>
454 
455  /**
456  * @brief Allocate memory.
457  * @param __a An allocator.
458  * @param __n The number of objects to allocate space for.
459  *
460  * Calls @c a.allocate(n)
461  */
462  _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
463  allocate(allocator_type& __a, size_type __n)
464  { return __a.allocate(__n); }
465 
466  /**
467  * @brief Allocate memory.
468  * @param __a An allocator.
469  * @param __n The number of objects to allocate space for.
470  * @param __hint Aid to locality.
471  * @return Memory of suitable size and alignment for @a n objects
472  * of type @c value_type
473  *
474  * Returns <tt> a.allocate(n, hint) </tt>
475  */
476  _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
477  allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
478  {
479 #if __cplusplus <= 201703L
480  return __a.allocate(__n, __hint);
481 #else
482  return __a.allocate(__n);
483 #endif
484  }
485 
486  /**
487  * @brief Deallocate memory.
488  * @param __a An allocator.
489  * @param __p Pointer to the memory to deallocate.
490  * @param __n The number of objects space was allocated for.
491  *
492  * Calls <tt> a.deallocate(p, n) </tt>
493  */
494  static _GLIBCXX20_CONSTEXPR void
495  deallocate(allocator_type& __a, pointer __p, size_type __n)
496  { __a.deallocate(__p, __n); }
497 
498  /**
499  * @brief Construct an object of type `_Up`
500  * @param __a An allocator.
501  * @param __p Pointer to memory of suitable size and alignment for
502  * an object of type `_Up`.
503  * @param __args Constructor arguments.
504  *
505  * Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
506  * in C++11, C++14 and C++17. Changed in C++20 to call
507  * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
508  */
509  template<typename _Up, typename... _Args>
510  static _GLIBCXX20_CONSTEXPR void
511  construct(allocator_type& __a __attribute__((__unused__)), _Up* __p,
512  _Args&&... __args)
514  {
515 #if __cplusplus <= 201703L
516  __a.construct(__p, std::forward<_Args>(__args)...);
517 #else
518  std::construct_at(__p, std::forward<_Args>(__args)...);
519 #endif
520  }
521 
522  /**
523  * @brief Destroy an object of type @a _Up
524  * @param __a An allocator.
525  * @param __p Pointer to the object to destroy
526  *
527  * Calls @c __a.destroy(__p).
528  */
529  template<typename _Up>
530  static _GLIBCXX20_CONSTEXPR void
531  destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p)
533  {
534 #if __cplusplus <= 201703L
535  __a.destroy(__p);
536 #else
537  std::destroy_at(__p);
538 #endif
539  }
540 
541  /**
542  * @brief The maximum supported allocation size
543  * @param __a An allocator.
544  * @return @c __a.max_size()
545  */
546  static _GLIBCXX20_CONSTEXPR size_type
547  max_size(const allocator_type& __a __attribute__((__unused__))) noexcept
548  {
549 #if __cplusplus <= 201703L
550  return __a.max_size();
551 #else
552  return size_t(-1) / sizeof(value_type);
553 #endif
554  }
555 
556  /**
557  * @brief Obtain an allocator to use when copying a container.
558  * @param __rhs An allocator.
559  * @return @c __rhs
560  */
561  static _GLIBCXX20_CONSTEXPR allocator_type
562  select_on_container_copy_construction(const allocator_type& __rhs)
563  { return __rhs; }
564  };
565 
566  /// Explicit specialization for std::allocator<void>.
567  template<>
569  {
570  /// The allocator type
571  using allocator_type = allocator<void>;
572 
573  /// The allocated type
574  using value_type = void;
575 
576  /// The allocator's pointer type.
577  using pointer = void*;
578 
579  /// The allocator's const pointer type.
580  using const_pointer = const void*;
581 
582  /// The allocator's void pointer type.
583  using void_pointer = void*;
584 
585  /// The allocator's const void pointer type.
586  using const_void_pointer = const void*;
587 
588  /// The allocator's difference type
589  using difference_type = std::ptrdiff_t;
590 
591  /// The allocator's size type
592  using size_type = std::size_t;
593 
594  /// How the allocator is propagated on copy assignment
596 
597  /// How the allocator is propagated on move assignment
599 
600  /// How the allocator is propagated on swap
602 
603  /// Whether all instances of the allocator type compare equal.
605 
606  template<typename _Up>
608 
609  template<typename _Up>
611 
612  /// allocate is ill-formed for allocator<void>
613  static void*
614  allocate(allocator_type&, size_type, const void* = nullptr) = delete;
615 
616  /// deallocate is ill-formed for allocator<void>
617  static void
618  deallocate(allocator_type&, void*, size_type) = delete;
619 
620  /**
621  * @brief Construct an object of type `_Up`
622  * @param __a An allocator.
623  * @param __p Pointer to memory of suitable size and alignment for
624  * an object of type `_Up`.
625  * @param __args Constructor arguments.
626  *
627  * Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
628  * in C++11, C++14 and C++17. Changed in C++20 to call
629  * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
630  */
631  template<typename _Up, typename... _Args>
632  static _GLIBCXX20_CONSTEXPR void
633  construct(allocator_type&, _Up* __p, _Args&&... __args)
635  { std::_Construct(__p, std::forward<_Args>(__args)...); }
636 
637  /**
638  * @brief Destroy an object of type `_Up`
639  * @param __a An allocator.
640  * @param __p Pointer to the object to destroy
641  *
642  * Invokes the destructor for `*__p`.
643  */
644  template<typename _Up>
645  static _GLIBCXX20_CONSTEXPR void
646  destroy(allocator_type&, _Up* __p)
648  { std::_Destroy(__p); }
649 
650  /// max_size is ill-formed for allocator<void>
651  static size_type
652  max_size(const allocator_type&) = delete;
653 
654  /**
655  * @brief Obtain an allocator to use when copying a container.
656  * @param __rhs An allocator.
657  * @return `__rhs`
658  */
659  static _GLIBCXX20_CONSTEXPR allocator_type
660  select_on_container_copy_construction(const allocator_type& __rhs)
661  { return __rhs; }
662  };
663 
664  /// @cond undocumented
665 #if __cplusplus < 201703L
666  template<typename _Alloc>
667  inline void
668  __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
669  { __one = __two; }
670 
671  template<typename _Alloc>
672  inline void
673  __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
674  { }
675 #endif
676 
677  template<typename _Alloc>
678  _GLIBCXX14_CONSTEXPR inline void
679  __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
680  {
681  typedef allocator_traits<_Alloc> __traits;
682  typedef typename __traits::propagate_on_container_copy_assignment __pocca;
683 #if __cplusplus >= 201703L
684  if constexpr (__pocca::value)
685  __one = __two;
686 #else
687  __do_alloc_on_copy(__one, __two, __pocca());
688 #endif
689  }
690 
691  template<typename _Alloc>
692  constexpr _Alloc
693  __alloc_on_copy(const _Alloc& __a)
694  {
695  typedef allocator_traits<_Alloc> __traits;
696  return __traits::select_on_container_copy_construction(__a);
697  }
698 
699 #if __cplusplus < 201703L
700  template<typename _Alloc>
701  inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
702  { __one = std::move(__two); }
703 
704  template<typename _Alloc>
705  inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
706  { }
707 #endif
708 
709  template<typename _Alloc>
710  _GLIBCXX14_CONSTEXPR inline void
711  __alloc_on_move(_Alloc& __one, _Alloc& __two)
712  {
713  typedef allocator_traits<_Alloc> __traits;
714  typedef typename __traits::propagate_on_container_move_assignment __pocma;
715 #if __cplusplus >= 201703L
716  if constexpr (__pocma::value)
717  __one = std::move(__two);
718 #else
719  __do_alloc_on_move(__one, __two, __pocma());
720 #endif
721  }
722 
723 #if __cplusplus < 201703L
724  template<typename _Alloc>
725  inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
726  {
727  using std::swap;
728  swap(__one, __two);
729  }
730 
731  template<typename _Alloc>
732  inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
733  { }
734 #endif
735 
736  template<typename _Alloc>
737  _GLIBCXX14_CONSTEXPR inline void
738  __alloc_on_swap(_Alloc& __one, _Alloc& __two)
739  {
740  typedef allocator_traits<_Alloc> __traits;
741  typedef typename __traits::propagate_on_container_swap __pocs;
742 #if __cplusplus >= 201703L
743  if constexpr (__pocs::value)
744  {
745  using std::swap;
746  swap(__one, __two);
747  }
748 #else
749  __do_alloc_on_swap(__one, __two, __pocs());
750 #endif
751  }
752 
753  template<typename _Alloc, typename _Tp,
754  typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
755  typename = void>
756  struct __is_alloc_insertable_impl
757  : false_type
758  { };
759 
760  template<typename _Alloc, typename _Tp, typename _ValueT>
761  struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
762  __void_t<decltype(allocator_traits<_Alloc>::construct(
763  std::declval<_Alloc&>(), std::declval<_ValueT*>(),
764  std::declval<_Tp>()))>>
765  : true_type
766  { };
767 
768  // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
769  // (might be wrong if _Alloc::construct exists but is not constrained,
770  // i.e. actually trying to use it would still be invalid. Use with caution.)
771  template<typename _Alloc>
772  struct __is_copy_insertable
773  : __is_alloc_insertable_impl<_Alloc,
774  typename _Alloc::value_type const&>::type
775  { };
776 
777  // std::allocator<_Tp> just requires CopyConstructible
778  template<typename _Tp>
779  struct __is_copy_insertable<allocator<_Tp>>
780  : is_copy_constructible<_Tp>
781  { };
782 
783  // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
784  // (might be wrong if _Alloc::construct exists but is not constrained,
785  // i.e. actually trying to use it would still be invalid. Use with caution.)
786  template<typename _Alloc>
787  struct __is_move_insertable
788  : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
789  { };
790 
791  // std::allocator<_Tp> just requires MoveConstructible
792  template<typename _Tp>
793  struct __is_move_insertable<allocator<_Tp>>
794  : is_move_constructible<_Tp>
795  { };
796 
797  // Trait to detect Allocator-like types.
798  template<typename _Alloc, typename = void>
799  struct __is_allocator : false_type { };
800 
801  template<typename _Alloc>
802  struct __is_allocator<_Alloc,
803  __void_t<typename _Alloc::value_type,
804  decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
805  : true_type { };
806 
807  template<typename _Alloc>
808  using _RequireAllocator
809  = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
810 
811  template<typename _Alloc>
812  using _RequireNotAllocator
813  = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
814 
815 #if __cpp_concepts >= 201907L
816  template<typename _Alloc>
817  concept __allocator_like = requires (_Alloc& __a) {
818  typename _Alloc::value_type;
819  __a.deallocate(__a.allocate(1u), 1u);
820  };
821 #endif
822  /// @endcond
823 #endif // C++11
824 
825  /// @cond undocumented
826 
827  /**
828  * Destroy a range of objects using the supplied allocator. For
829  * non-default allocators we do not optimize away invocation of
830  * destroy() even if _Tp has a trivial destructor.
831  */
832 
833  template<typename _ForwardIterator, typename _Allocator>
834  _GLIBCXX20_CONSTEXPR
835  void
836  _Destroy(_ForwardIterator __first, _ForwardIterator __last,
837  _Allocator& __alloc)
838  {
839  for (; __first != __last; ++__first)
840 #if __cplusplus < 201103L
841  __alloc.destroy(std::__addressof(*__first));
842 #else
844  std::__addressof(*__first));
845 #endif
846  }
847 
848  template<typename _ForwardIterator, typename _Tp>
849  _GLIBCXX20_CONSTEXPR
850  inline void
851  _Destroy(_ForwardIterator __first, _ForwardIterator __last,
853  {
854  std::_Destroy(__first, __last);
855  }
856  /// @endcond
857 
858 _GLIBCXX_END_NAMESPACE_VERSION
859 } // namespace std
860 #endif // _ALLOC_TRAITS_H
static constexpr pointer allocate(_Alloc &__a, size_type __n, const_void_pointer __hint)
Allocate memory.
static constexpr size_type max_size(const allocator_type &__a) noexcept
The maximum supported allocation size.
std::size_t size_type
The allocator&#39;s size type.
is_nothrow_constructible
Definition: type_traits:1047
__detected_or_t< value_type *, __pointer, _Tp_alloc_type > pointer
The allocator&#39;s pointer type.
typename _Diff< _Tp_alloc_type, pointer >::type difference_type
The allocator&#39;s difference type.
static constexpr pointer allocate(allocator_type &__a, size_type __n, const_void_pointer __hint)
Allocate memory.
std::size_t size_type
The allocator&#39;s size type.
__detected_or_t< false_type, __pocca, _Tp_alloc_type > propagate_on_container_copy_assignment
How the allocator is propagated on copy assignment.
static constexpr void deallocate(allocator_type &__a, pointer __p, size_type __n)
Deallocate memory.
static constexpr auto construct(_Alloc &__a, _Tp *__p, _Args &&... __args) noexcept(noexcept(_S_construct(__a, __p, std::forward< _Args >(__args)...))) -> decltype(_S_construct(__a, __p, std::forward< _Args >(__args)...))
Construct an object of type _Tp
make_unsigned
Definition: type_traits:1859
void * pointer
The allocator&#39;s pointer type.
is_move_constructible
Definition: type_traits:1032
typename _Ptr< __cv_pointer, const void >::type const_void_pointer
The allocator&#39;s const void pointer type.
Uniform interface to all allocator types.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:104
typename _Ptr< __c_pointer, const value_type >::type const_pointer
The allocator&#39;s const pointer type.
_Tp * pointer
The allocator&#39;s pointer type.
std::ptrdiff_t difference_type
The allocator&#39;s difference type.
void * void_pointer
The allocator&#39;s void pointer type.
typename _Ptr< __v_pointer, void >::type void_pointer
The allocator&#39;s void pointer type.
const _Tp * const_pointer
The allocator&#39;s const pointer type.
static constexpr void construct(allocator_type &__a, _Up *__p, _Args &&... __args) noexcept(std::is_nothrow_constructible< _Up, _Args... >::value)
Construct an object of type _Up
ISO C++ entities toplevel namespace is std.
static constexpr size_type max_size(const _Alloc &__a) noexcept
The maximum supported allocation size.
static constexpr void destroy(_Alloc &__a, _Tp *__p) noexcept(noexcept(_S_destroy(__a, __p, 0)))
Destroy an object of type _Tp.
static constexpr allocator_type select_on_container_copy_construction(const allocator_type &__rhs)
Obtain an allocator to use when copying a container.
__detected_or_t< false_type, __pocs, _Tp_alloc_type > propagate_on_container_swap
How the allocator is propagated on swap.
std::ptrdiff_t difference_type
The allocator&#39;s difference type.
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:82
constexpr void _Construct(_Tp *__p, _Args &&... __args)
static constexpr pointer allocate(_Alloc &__a, size_type __n)
Allocate memory.
const void * const_pointer
The allocator&#39;s const pointer type.
typename __detected_or_t< is_empty< _Tp_alloc_type >, __equal, _Tp_alloc_type >::type is_always_equal
Whether all instances of the allocator type compare equal.
is_constructible
Definition: type_traits:977
The standard allocator, as per C++03 [20.4.1].
Definition: allocator.h:129
_Alloc::value_type value_type
The allocated type.
_Alloc allocator_type
The allocator type.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:49
constexpr void _Destroy(_ForwardIterator __first, _ForwardIterator __last)
const void * const_void_pointer
The allocator&#39;s const void pointer type.
static constexpr pointer allocate(allocator_type &__a, size_type __n)
Allocate memory.
static constexpr void construct(allocator_type &, _Up *__p, _Args &&... __args) noexcept(std::is_nothrow_constructible< _Up, _Args... >::value)
Construct an object of type _Up
is_copy_constructible
Definition: type_traits:1009
static constexpr allocator_type select_on_container_copy_construction(const allocator_type &__rhs)
Obtain an allocator to use when copying a container.
void * void_pointer
The allocator&#39;s void pointer type.
__detected_or_t< false_type, __pocma, _Tp_alloc_type > propagate_on_container_move_assignment
How the allocator is propagated on move assignment.
static constexpr void deallocate(_Alloc &__a, pointer __p, size_type __n)
Deallocate memory.
typename _Size< _Tp_alloc_type, difference_type >::type size_type
The allocator&#39;s size type.
Define a member typedef type only if a boolean constant is true.
Definition: type_traits:2222
integral_constant< bool, false > false_type
The type used as a compile-time boolean with false value.
Definition: type_traits:85
Uniform interface to all pointer-like types.
Definition: ptr_traits.h:181
static constexpr void destroy(allocator_type &__a, _Up *__p) noexcept(is_nothrow_destructible< _Up >::value)
Destroy an object of type _Up.
const void * const_void_pointer
The allocator&#39;s const void pointer type.
is_nothrow_destructible
Definition: type_traits:961
static constexpr void destroy(allocator_type &, _Up *__p) noexcept(is_nothrow_destructible< _Up >::value)
Destroy an object of type _Up
integral_constant
Definition: type_traits:62
static constexpr _Alloc select_on_container_copy_construction(const _Alloc &__rhs)
Obtain an allocator to use when copying a container.