libstdc++
bits/alloc_traits.h
Go to the documentation of this file.
1 // Allocator traits -*- C++ -*-
2 
3 // Copyright (C) 2011-2021 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 201411
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 #if __cplusplus < 201703L
567  template<typename _Alloc>
568  inline void
569  __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
570  { __one = __two; }
571 
572  template<typename _Alloc>
573  inline void
574  __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
575  { }
576 #endif
577 
578  template<typename _Alloc>
579  _GLIBCXX14_CONSTEXPR inline void
580  __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
581  {
582  typedef allocator_traits<_Alloc> __traits;
583  typedef typename __traits::propagate_on_container_copy_assignment __pocca;
584 #if __cplusplus >= 201703L
585  if constexpr (__pocca::value)
586  __one = __two;
587 #else
588  __do_alloc_on_copy(__one, __two, __pocca());
589 #endif
590  }
591 
592  template<typename _Alloc>
593  constexpr _Alloc
594  __alloc_on_copy(const _Alloc& __a)
595  {
596  typedef allocator_traits<_Alloc> __traits;
597  return __traits::select_on_container_copy_construction(__a);
598  }
599 
600 #if __cplusplus < 201703L
601  template<typename _Alloc>
602  inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
603  { __one = std::move(__two); }
604 
605  template<typename _Alloc>
606  inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
607  { }
608 #endif
609 
610  template<typename _Alloc>
611  _GLIBCXX14_CONSTEXPR inline void
612  __alloc_on_move(_Alloc& __one, _Alloc& __two)
613  {
614  typedef allocator_traits<_Alloc> __traits;
615  typedef typename __traits::propagate_on_container_move_assignment __pocma;
616 #if __cplusplus >= 201703L
617  if constexpr (__pocma::value)
618  __one = std::move(__two);
619 #else
620  __do_alloc_on_move(__one, __two, __pocma());
621 #endif
622  }
623 
624 #if __cplusplus < 201703L
625  template<typename _Alloc>
626  inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
627  {
628  using std::swap;
629  swap(__one, __two);
630  }
631 
632  template<typename _Alloc>
633  inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
634  { }
635 #endif
636 
637  template<typename _Alloc>
638  _GLIBCXX14_CONSTEXPR inline void
639  __alloc_on_swap(_Alloc& __one, _Alloc& __two)
640  {
641  typedef allocator_traits<_Alloc> __traits;
642  typedef typename __traits::propagate_on_container_swap __pocs;
643 #if __cplusplus >= 201703L
644  if constexpr (__pocs::value)
645  {
646  using std::swap;
647  swap(__one, __two);
648  }
649 #else
650  __do_alloc_on_swap(__one, __two, __pocs());
651 #endif
652  }
653 
654  template<typename _Alloc, typename _Tp,
655  typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
656  typename = void>
657  struct __is_alloc_insertable_impl
658  : false_type
659  { };
660 
661  template<typename _Alloc, typename _Tp, typename _ValueT>
662  struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
663  __void_t<decltype(allocator_traits<_Alloc>::construct(
664  std::declval<_Alloc&>(), std::declval<_ValueT*>(),
665  std::declval<_Tp>()))>>
666  : true_type
667  { };
668 
669  // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
670  // (might be wrong if _Alloc::construct exists but is not constrained,
671  // i.e. actually trying to use it would still be invalid. Use with caution.)
672  template<typename _Alloc>
673  struct __is_copy_insertable
674  : __is_alloc_insertable_impl<_Alloc,
675  typename _Alloc::value_type const&>::type
676  { };
677 
678  // std::allocator<_Tp> just requires CopyConstructible
679  template<typename _Tp>
680  struct __is_copy_insertable<allocator<_Tp>>
681  : is_copy_constructible<_Tp>
682  { };
683 
684  // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
685  // (might be wrong if _Alloc::construct exists but is not constrained,
686  // i.e. actually trying to use it would still be invalid. Use with caution.)
687  template<typename _Alloc>
688  struct __is_move_insertable
689  : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
690  { };
691 
692  // std::allocator<_Tp> just requires MoveConstructible
693  template<typename _Tp>
694  struct __is_move_insertable<allocator<_Tp>>
695  : is_move_constructible<_Tp>
696  { };
697 
698  // Trait to detect Allocator-like types.
699  template<typename _Alloc, typename = void>
700  struct __is_allocator : false_type { };
701 
702  template<typename _Alloc>
703  struct __is_allocator<_Alloc,
704  __void_t<typename _Alloc::value_type,
705  decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
706  : true_type { };
707 
708  template<typename _Alloc>
709  using _RequireAllocator
710  = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
711 
712  template<typename _Alloc>
713  using _RequireNotAllocator
714  = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
715 
716 #if __cpp_concepts >= 201907L
717  template<typename _Alloc>
718  concept __allocator_like = requires (_Alloc& __a) {
719  typename _Alloc::value_type;
720  __a.deallocate(__a.allocate(1u), 1u);
721  };
722 #endif
723 #endif // C++11
724 
725  /**
726  * Destroy a range of objects using the supplied allocator. For
727  * non-default allocators we do not optimize away invocation of
728  * destroy() even if _Tp has a trivial destructor.
729  */
730 
731  template<typename _ForwardIterator, typename _Allocator>
732  void
733  _Destroy(_ForwardIterator __first, _ForwardIterator __last,
734  _Allocator& __alloc)
735  {
736  for (; __first != __last; ++__first)
737 #if __cplusplus < 201103L
738  __alloc.destroy(std::__addressof(*__first));
739 #else
741  std::__addressof(*__first));
742 #endif
743  }
744 
745  template<typename _ForwardIterator, typename _Tp>
746  inline void
747  _Destroy(_ForwardIterator __first, _ForwardIterator __last,
748  allocator<_Tp>&)
749  {
750  _Destroy(__first, __last);
751  }
752 
753 _GLIBCXX_END_NAMESPACE_VERSION
754 } // namespace std
755 #endif // _ALLOC_TRAITS_H
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:83
integral_constant< bool, false > false_type
The type used as a compile-time boolean with false value.
Definition: type_traits:86
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:428
ISO C++ entities toplevel namespace is std.
void _Destroy(_ForwardIterator __first, _ForwardIterator __last, _Allocator &__alloc)
integral_constant
Definition: type_traits:66
is_nothrow_destructible
Definition: type_traits:938
is_nothrow_constructible
Definition: type_traits:1024
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.
The standard allocator, as per C++03 [20.4.1].
Definition: allocator.h:141
Uniform interface to all pointer-like types.
Definition: ptr_traits.h:101
__detected_or_t< ptrdiff_t, __difference_type, _Ptr > difference_type
The type used to represent the difference between two pointers.
Definition: ptr_traits.h:119