LCOV - code coverage report
Current view: top level - /usr/include/c++/14/bits - alloc_traits.h Coverage Total Hit
Test: PostgreSQL 19devel Lines: 0.0 % 4 0
Test Date: 2026-02-27 05:14:50 Functions: - 0 0
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.0-1