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 = 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  */
210  = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
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, ...)
277  noexcept(std::is_nothrow_destructible<_Tp>::value)
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
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
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
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
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
563  { return __rhs; }
564  };
565 
566  /// Explicit specialization for std::allocator<void>.
567  template<>
569  {
570  /// The allocator type
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
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
661  { return __rhs; }
662  };
663 
664 #if __cplusplus < 201703L
665  template<typename _Alloc>
666  inline void
667  __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
668  { __one = __two; }
669 
670  template<typename _Alloc>
671  inline void
672  __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
673  { }
674 #endif
675 
676  template<typename _Alloc>
677  _GLIBCXX14_CONSTEXPR inline void
678  __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
679  {
680  typedef allocator_traits<_Alloc> __traits;
681  typedef typename __traits::propagate_on_container_copy_assignment __pocca;
682 #if __cplusplus >= 201703L
683  if constexpr (__pocca::value)
684  __one = __two;
685 #else
686  __do_alloc_on_copy(__one, __two, __pocca());
687 #endif
688  }
689 
690  template<typename _Alloc>
691  constexpr _Alloc
692  __alloc_on_copy(const _Alloc& __a)
693  {
694  typedef allocator_traits<_Alloc> __traits;
695  return __traits::select_on_container_copy_construction(__a);
696  }
697 
698 #if __cplusplus < 201703L
699  template<typename _Alloc>
700  inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
701  { __one = std::move(__two); }
702 
703  template<typename _Alloc>
704  inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
705  { }
706 #endif
707 
708  template<typename _Alloc>
709  _GLIBCXX14_CONSTEXPR inline void
710  __alloc_on_move(_Alloc& __one, _Alloc& __two)
711  {
712  typedef allocator_traits<_Alloc> __traits;
713  typedef typename __traits::propagate_on_container_move_assignment __pocma;
714 #if __cplusplus >= 201703L
715  if constexpr (__pocma::value)
716  __one = std::move(__two);
717 #else
718  __do_alloc_on_move(__one, __two, __pocma());
719 #endif
720  }
721 
722 #if __cplusplus < 201703L
723  template<typename _Alloc>
724  inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
725  {
726  using std::swap;
727  swap(__one, __two);
728  }
729 
730  template<typename _Alloc>
731  inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
732  { }
733 #endif
734 
735  template<typename _Alloc>
736  _GLIBCXX14_CONSTEXPR inline void
737  __alloc_on_swap(_Alloc& __one, _Alloc& __two)
738  {
739  typedef allocator_traits<_Alloc> __traits;
740  typedef typename __traits::propagate_on_container_swap __pocs;
741 #if __cplusplus >= 201703L
742  if constexpr (__pocs::value)
743  {
744  using std::swap;
745  swap(__one, __two);
746  }
747 #else
748  __do_alloc_on_swap(__one, __two, __pocs());
749 #endif
750  }
751 
752  template<typename _Alloc, typename _Tp,
753  typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
754  typename = void>
755  struct __is_alloc_insertable_impl
756  : false_type
757  { };
758 
759  template<typename _Alloc, typename _Tp, typename _ValueT>
760  struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
761  __void_t<decltype(allocator_traits<_Alloc>::construct(
762  std::declval<_Alloc&>(), std::declval<_ValueT*>(),
763  std::declval<_Tp>()))>>
764  : true_type
765  { };
766 
767  // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
768  // (might be wrong if _Alloc::construct exists but is not constrained,
769  // i.e. actually trying to use it would still be invalid. Use with caution.)
770  template<typename _Alloc>
771  struct __is_copy_insertable
772  : __is_alloc_insertable_impl<_Alloc,
773  typename _Alloc::value_type const&>::type
774  { };
775 
776  // std::allocator<_Tp> just requires CopyConstructible
777  template<typename _Tp>
778  struct __is_copy_insertable<allocator<_Tp>>
779  : is_copy_constructible<_Tp>
780  { };
781 
782  // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
783  // (might be wrong if _Alloc::construct exists but is not constrained,
784  // i.e. actually trying to use it would still be invalid. Use with caution.)
785  template<typename _Alloc>
786  struct __is_move_insertable
787  : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
788  { };
789 
790  // std::allocator<_Tp> just requires MoveConstructible
791  template<typename _Tp>
792  struct __is_move_insertable<allocator<_Tp>>
793  : is_move_constructible<_Tp>
794  { };
795 
796  // Trait to detect Allocator-like types.
797  template<typename _Alloc, typename = void>
798  struct __is_allocator : false_type { };
799 
800  template<typename _Alloc>
801  struct __is_allocator<_Alloc,
802  __void_t<typename _Alloc::value_type,
803  decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
804  : true_type { };
805 
806  template<typename _Alloc>
807  using _RequireAllocator
808  = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
809 
810  template<typename _Alloc>
811  using _RequireNotAllocator
812  = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
813 
814 #if __cpp_concepts >= 201907L
815  template<typename _Alloc>
816  concept __allocator_like = requires (_Alloc& __a) {
817  typename _Alloc::value_type;
818  __a.deallocate(__a.allocate(1u), 1u);
819  };
820 #endif
821 #endif // C++11
822 
823  /**
824  * Destroy a range of objects using the supplied allocator. For
825  * non-default allocators we do not optimize away invocation of
826  * destroy() even if _Tp has a trivial destructor.
827  */
828 
829  template<typename _ForwardIterator, typename _Allocator>
830  _GLIBCXX20_CONSTEXPR
831  void
832  _Destroy(_ForwardIterator __first, _ForwardIterator __last,
833  _Allocator& __alloc)
834  {
835  for (; __first != __last; ++__first)
836 #if __cplusplus < 201103L
837  __alloc.destroy(std::__addressof(*__first));
838 #else
840  std::__addressof(*__first));
841 #endif
842  }
843 
844  template<typename _ForwardIterator, typename _Tp>
845  _GLIBCXX20_CONSTEXPR
846  inline void
847  _Destroy(_ForwardIterator __first, _ForwardIterator __last,
848  allocator<_Tp>&)
849  {
850  _Destroy(__first, __last);
851  }
852 
853 _GLIBCXX_END_NAMESPACE_VERSION
854 } // namespace std
855 #endif // _ALLOC_TRAITS_H
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:82
integral_constant< bool, false > false_type
The type used as a compile-time boolean with false value.
Definition: type_traits:85
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:49
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:104
void swap(any &__x, any &__y) noexcept
Exchange the states of two any objects.
Definition: any:429
ISO C++ entities toplevel namespace is std.
constexpr void _Construct(_Tp *__p, _Args &&... __args)
constexpr void _Destroy(_ForwardIterator __first, _ForwardIterator __last, _Allocator &__alloc)
integral_constant
Definition: type_traits:63
is_nothrow_destructible
Definition: type_traits:963
is_nothrow_constructible
Definition: type_traits:1049
Uniform interface to all allocator types.
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
__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.
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.
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.
__detected_or_t< typename is_empty< _Alloc >::type, __equal, _Alloc > is_always_equal
Whether all instances of the allocator type compare equal.
_Alloc allocator_type
The allocator type.
allocator< _Tp > allocator_type
The allocator type.
void * void_pointer
The allocator's void pointer type.
_Tp * pointer
The allocator's pointer type.
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.
const _Tp * const_pointer
The allocator's const pointer type.
const void * const_void_pointer
The allocator's const void pointer type.
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 construct(allocator_type &__a, _Up *__p, _Args &&... __args) noexcept(std::is_nothrow_constructible< _Up, _Args... >::value)
Construct an object of type _Up
static constexpr void destroy(allocator_type &__a, _Up *__p) noexcept(is_nothrow_destructible< _Up >::value)
Destroy an object of type _Up.
std::size_t size_type
The allocator's size type.
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>
static constexpr void construct(allocator_type &, _Up *__p, _Args &&... __args) noexcept(std::is_nothrow_constructible< _Up, _Args... >::value)
Construct an object of type _Up
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.
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.
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
allocator<void> specialization.
Definition: allocator.h:73
The standard allocator, as per C++03 [20.4.1].
Definition: allocator.h:125
Uniform interface to all pointer-like types.
Definition: ptr_traits.h:195