libstdc++
alloc_traits.h
Go to the documentation of this file.
00001 // Allocator traits -*- C++ -*-
00002 
00003 // Copyright (C) 2011-2016 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file bits/alloc_traits.h
00026  *  This is an internal header file, included by other library headers.
00027  *  Do not attempt to use it directly. @headername{memory}
00028  */
00029 
00030 #ifndef _ALLOC_TRAITS_H
00031 #define _ALLOC_TRAITS_H 1
00032 
00033 #if __cplusplus >= 201103L
00034 
00035 #include <bits/memoryfwd.h>
00036 #include <bits/ptr_traits.h>
00037 #include <ext/numeric_traits.h>
00038 
00039 #define __cpp_lib_allocator_traits_is_always_equal 201411
00040 
00041 namespace std _GLIBCXX_VISIBILITY(default)
00042 {
00043 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00044 
00045   struct __allocator_traits_base
00046   {
00047     template<typename _Tp, typename _Up, typename = void>
00048       struct __rebind : __replace_first_arg<_Tp, _Up> { };
00049 
00050     template<typename _Tp, typename _Up>
00051       struct __rebind<_Tp, _Up,
00052                       __void_t<typename _Tp::template rebind<_Up>::other>>
00053       { using type = typename _Tp::template rebind<_Up>::other; };
00054 
00055   protected:
00056     template<typename _Tp>
00057       using __pointer = typename _Tp::pointer;
00058     template<typename _Tp>
00059       using __c_pointer = typename _Tp::const_pointer;
00060     template<typename _Tp>
00061       using __v_pointer = typename _Tp::void_pointer;
00062     template<typename _Tp>
00063       using __cv_pointer = typename _Tp::const_void_pointer;
00064     template<typename _Tp>
00065       using __pocca = typename _Tp::propagate_on_container_copy_assignment;
00066     template<typename _Tp>
00067       using __pocma = typename _Tp::propagate_on_container_move_assignment;
00068     template<typename _Tp>
00069       using __pocs = typename _Tp::propagate_on_container_swap;
00070     template<typename _Tp>
00071       using __equal = typename _Tp::is_always_equal;
00072   };
00073 
00074   template<typename _Alloc, typename _Up>
00075     using __alloc_rebind
00076       = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
00077 
00078   /**
00079    * @brief  Uniform interface to all allocator types.
00080    * @ingroup allocators
00081   */
00082   template<typename _Alloc>
00083     struct allocator_traits : __allocator_traits_base
00084     {
00085       /// The allocator type
00086       typedef _Alloc allocator_type;
00087       /// The allocated type
00088       typedef typename _Alloc::value_type value_type;
00089 
00090       /**
00091        * @brief   The allocator's pointer type.
00092        *
00093        * @c Alloc::pointer if that type exists, otherwise @c value_type*
00094       */
00095       using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
00096 
00097     private:
00098       // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
00099       template<template<typename> class _Func, typename _Tp, typename = void>
00100         struct _Ptr
00101         {
00102           using type = typename pointer_traits<pointer>::template rebind<_Tp>;
00103         };
00104 
00105       template<template<typename> class _Func, typename _Tp>
00106         struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
00107         {
00108           using type = _Func<_Alloc>;
00109         };
00110 
00111       // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
00112       template<typename _A2, typename _PtrT, typename = void>
00113         struct _Diff
00114         { using type = typename pointer_traits<_PtrT>::difference_type; };
00115 
00116       template<typename _A2, typename _PtrT>
00117         struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
00118         { using type = typename _A2::difference_type; };
00119 
00120       // Select _A2::size_type or make_unsigned<_DiffT>::type
00121       template<typename _A2, typename _DiffT, typename = void>
00122         struct _Size : make_unsigned<_DiffT> { };
00123 
00124       template<typename _A2, typename _DiffT>
00125         struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
00126         { using type = typename _A2::size_type; };
00127 
00128     public:
00129       /**
00130        * @brief   The allocator's const pointer type.
00131        *
00132        * @c Alloc::const_pointer if that type exists, otherwise
00133        * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
00134       */
00135       using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
00136 
00137       /**
00138        * @brief   The allocator's void pointer type.
00139        *
00140        * @c Alloc::void_pointer if that type exists, otherwise
00141        * <tt> pointer_traits<pointer>::rebind<void> </tt>
00142       */
00143       using void_pointer = typename _Ptr<__v_pointer, void>::type;
00144 
00145       /**
00146        * @brief   The allocator's const void pointer type.
00147        *
00148        * @c Alloc::const_void_pointer if that type exists, otherwise
00149        * <tt> pointer_traits<pointer>::rebind<const void> </tt>
00150       */
00151       using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
00152 
00153       /**
00154        * @brief   The allocator's difference type
00155        *
00156        * @c Alloc::difference_type if that type exists, otherwise
00157        * <tt> pointer_traits<pointer>::difference_type </tt>
00158       */
00159       using difference_type = typename _Diff<_Alloc, pointer>::type;
00160 
00161       /**
00162        * @brief   The allocator's size type
00163        *
00164        * @c Alloc::size_type if that type exists, otherwise
00165        * <tt> make_unsigned<difference_type>::type </tt>
00166       */
00167       using size_type = typename _Size<_Alloc, difference_type>::type;
00168 
00169       /**
00170        * @brief   How the allocator is propagated on copy assignment
00171        *
00172        * @c Alloc::propagate_on_container_copy_assignment if that type exists,
00173        * otherwise @c false_type
00174       */
00175       using propagate_on_container_copy_assignment
00176         = __detected_or_t<false_type, __pocca, _Alloc>;
00177 
00178       /**
00179        * @brief   How the allocator is propagated on move assignment
00180        *
00181        * @c Alloc::propagate_on_container_move_assignment if that type exists,
00182        * otherwise @c false_type
00183       */
00184       using propagate_on_container_move_assignment
00185         = __detected_or_t<false_type, __pocma, _Alloc>;
00186 
00187       /**
00188        * @brief   How the allocator is propagated on swap
00189        *
00190        * @c Alloc::propagate_on_container_swap if that type exists,
00191        * otherwise @c false_type
00192       */
00193       using propagate_on_container_swap
00194         = __detected_or_t<false_type, __pocs, _Alloc>;
00195 
00196       /**
00197        * @brief   Whether all instances of the allocator type compare equal.
00198        *
00199        * @c Alloc::is_always_equal if that type exists,
00200        * otherwise @c is_empty<Alloc>::type
00201       */
00202       using is_always_equal
00203         = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
00204 
00205       template<typename _Tp>
00206         using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
00207       template<typename _Tp>
00208         using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
00209 
00210     private:
00211       template<typename _Alloc2>
00212         static auto
00213         _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
00214         -> decltype(__a.allocate(__n, __hint))
00215         { return __a.allocate(__n, __hint); }
00216 
00217       template<typename _Alloc2>
00218         static pointer
00219         _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
00220         { return __a.allocate(__n); }
00221 
00222       template<typename _Tp, typename... _Args>
00223         struct __construct_helper
00224         {
00225           template<typename _Alloc2,
00226             typename = decltype(std::declval<_Alloc2*>()->construct(
00227                   std::declval<_Tp*>(), std::declval<_Args>()...))>
00228             static true_type __test(int);
00229 
00230           template<typename>
00231             static false_type __test(...);
00232 
00233           using type = decltype(__test<_Alloc>(0));
00234         };
00235 
00236       template<typename _Tp, typename... _Args>
00237         using __has_construct
00238           = typename __construct_helper<_Tp, _Args...>::type;
00239 
00240       template<typename _Tp, typename... _Args>
00241         static _Require<__has_construct<_Tp, _Args...>>
00242         _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
00243         { __a.construct(__p, std::forward<_Args>(__args)...); }
00244 
00245       template<typename _Tp, typename... _Args>
00246         static
00247         _Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
00248                                is_constructible<_Tp, _Args...>>>
00249         _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
00250         { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
00251 
00252       template<typename _Alloc2, typename _Tp>
00253         static auto
00254         _S_destroy(_Alloc2& __a, _Tp* __p, int)
00255         -> decltype(__a.destroy(__p))
00256         { __a.destroy(__p); }
00257 
00258       template<typename _Alloc2, typename _Tp>
00259         static void
00260         _S_destroy(_Alloc2&, _Tp* __p, ...)
00261         { __p->~_Tp(); }
00262 
00263       template<typename _Alloc2>
00264         static auto
00265         _S_max_size(_Alloc2& __a, int)
00266         -> decltype(__a.max_size())
00267         { return __a.max_size(); }
00268 
00269       template<typename _Alloc2>
00270         static size_type
00271         _S_max_size(_Alloc2&, ...)
00272         {
00273           // _GLIBCXX_RESOLVE_LIB_DEFECTS
00274           // 2466. allocator_traits::max_size() default behavior is incorrect
00275           return __gnu_cxx::__numeric_traits<size_type>::__max
00276             / sizeof(value_type);
00277         }
00278 
00279       template<typename _Alloc2>
00280         static auto
00281         _S_select(_Alloc2& __a, int)
00282         -> decltype(__a.select_on_container_copy_construction())
00283         { return __a.select_on_container_copy_construction(); }
00284 
00285       template<typename _Alloc2>
00286         static _Alloc2
00287         _S_select(_Alloc2& __a, ...)
00288         { return __a; }
00289 
00290     public:
00291 
00292       /**
00293        *  @brief  Allocate memory.
00294        *  @param  __a  An allocator.
00295        *  @param  __n  The number of objects to allocate space for.
00296        *
00297        *  Calls @c a.allocate(n)
00298       */
00299       static pointer
00300       allocate(_Alloc& __a, size_type __n)
00301       { return __a.allocate(__n); }
00302 
00303       /**
00304        *  @brief  Allocate memory.
00305        *  @param  __a  An allocator.
00306        *  @param  __n  The number of objects to allocate space for.
00307        *  @param  __hint Aid to locality.
00308        *  @return Memory of suitable size and alignment for @a n objects
00309        *          of type @c value_type
00310        *
00311        *  Returns <tt> a.allocate(n, hint) </tt> if that expression is
00312        *  well-formed, otherwise returns @c a.allocate(n)
00313       */
00314       static pointer
00315       allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
00316       { return _S_allocate(__a, __n, __hint, 0); }
00317 
00318       /**
00319        *  @brief  Deallocate memory.
00320        *  @param  __a  An allocator.
00321        *  @param  __p  Pointer to the memory to deallocate.
00322        *  @param  __n  The number of objects space was allocated for.
00323        *
00324        *  Calls <tt> a.deallocate(p, n) </tt>
00325       */
00326       static void
00327       deallocate(_Alloc& __a, pointer __p, size_type __n)
00328       { __a.deallocate(__p, __n); }
00329 
00330       /**
00331        *  @brief  Construct an object of type @a _Tp
00332        *  @param  __a  An allocator.
00333        *  @param  __p  Pointer to memory of suitable size and alignment for Tp
00334        *  @param  __args Constructor arguments.
00335        *
00336        *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
00337        *  if that expression is well-formed, otherwise uses placement-new
00338        *  to construct an object of type @a _Tp at location @a __p from the
00339        *  arguments @a __args...
00340       */
00341       template<typename _Tp, typename... _Args>
00342         static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
00343         -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
00344         { _S_construct(__a, __p, std::forward<_Args>(__args)...); }
00345 
00346       /**
00347        *  @brief  Destroy an object of type @a _Tp
00348        *  @param  __a  An allocator.
00349        *  @param  __p  Pointer to the object to destroy
00350        *
00351        *  Calls @c __a.destroy(__p) if that expression is well-formed,
00352        *  otherwise calls @c __p->~_Tp()
00353       */
00354       template<typename _Tp>
00355         static void destroy(_Alloc& __a, _Tp* __p)
00356         { _S_destroy(__a, __p, 0); }
00357 
00358       /**
00359        *  @brief  The maximum supported allocation size
00360        *  @param  __a  An allocator.
00361        *  @return @c __a.max_size() or @c numeric_limits<size_type>::max()
00362        *
00363        *  Returns @c __a.max_size() if that expression is well-formed,
00364        *  otherwise returns @c numeric_limits<size_type>::max()
00365       */
00366       static size_type max_size(const _Alloc& __a) noexcept
00367       { return _S_max_size(__a, 0); }
00368 
00369       /**
00370        *  @brief  Obtain an allocator to use when copying a container.
00371        *  @param  __rhs  An allocator.
00372        *  @return @c __rhs.select_on_container_copy_construction() or @a __rhs
00373        *
00374        *  Returns @c __rhs.select_on_container_copy_construction() if that
00375        *  expression is well-formed, otherwise returns @a __rhs
00376       */
00377       static _Alloc
00378       select_on_container_copy_construction(const _Alloc& __rhs)
00379       { return _S_select(__rhs, 0); }
00380     };
00381 
00382   /// Partial specialization for std::allocator.
00383   template<typename _Tp>
00384     struct allocator_traits<allocator<_Tp>>
00385     {
00386       /// The allocator type
00387       using allocator_type = allocator<_Tp>;
00388       /// The allocated type
00389       using value_type = _Tp;
00390 
00391       /// The allocator's pointer type.
00392       using pointer = _Tp*;
00393 
00394       /// The allocator's const pointer type.
00395       using const_pointer = const _Tp*;
00396 
00397       /// The allocator's void pointer type.
00398       using void_pointer = void*;
00399 
00400       /// The allocator's const void pointer type.
00401       using const_void_pointer = const void*;
00402 
00403       /// The allocator's difference type
00404       using difference_type = std::ptrdiff_t;
00405 
00406       /// The allocator's size type
00407       using size_type = std::size_t;
00408 
00409       /// How the allocator is propagated on copy assignment
00410       using propagate_on_container_copy_assignment = false_type;
00411 
00412       /// How the allocator is propagated on move assignment
00413       using propagate_on_container_move_assignment = true_type;
00414 
00415       /// How the allocator is propagated on swap
00416       using propagate_on_container_swap = false_type;
00417 
00418       /// Whether all instances of the allocator type compare equal.
00419       using is_always_equal = true_type;
00420 
00421       template<typename _Up>
00422         using rebind_alloc = allocator<_Up>;
00423 
00424       template<typename _Up>
00425         using rebind_traits = allocator_traits<allocator<_Up>>;
00426 
00427       /**
00428        *  @brief  Allocate memory.
00429        *  @param  __a  An allocator.
00430        *  @param  __n  The number of objects to allocate space for.
00431        *
00432        *  Calls @c a.allocate(n)
00433       */
00434       static pointer
00435       allocate(allocator_type& __a, size_type __n)
00436       { return __a.allocate(__n); }
00437 
00438       /**
00439        *  @brief  Allocate memory.
00440        *  @param  __a  An allocator.
00441        *  @param  __n  The number of objects to allocate space for.
00442        *  @param  __hint Aid to locality.
00443        *  @return Memory of suitable size and alignment for @a n objects
00444        *          of type @c value_type
00445        *
00446        *  Returns <tt> a.allocate(n, hint) </tt>
00447       */
00448       static pointer
00449       allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
00450       { return __a.allocate(__n, __hint); }
00451 
00452       /**
00453        *  @brief  Deallocate memory.
00454        *  @param  __a  An allocator.
00455        *  @param  __p  Pointer to the memory to deallocate.
00456        *  @param  __n  The number of objects space was allocated for.
00457        *
00458        *  Calls <tt> a.deallocate(p, n) </tt>
00459       */
00460       static void
00461       deallocate(allocator_type& __a, pointer __p, size_type __n)
00462       { __a.deallocate(__p, __n); }
00463 
00464       /**
00465        *  @brief  Construct an object of type @a _Up
00466        *  @param  __a  An allocator.
00467        *  @param  __p  Pointer to memory of suitable size and alignment for Tp
00468        *  @param  __args Constructor arguments.
00469        *
00470        *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
00471       */
00472       template<typename _Up, typename... _Args>
00473         static void
00474         construct(allocator_type& __a, _Up* __p, _Args&&... __args)
00475         { __a.construct(__p, std::forward<_Args>(__args)...); }
00476 
00477       /**
00478        *  @brief  Destroy an object of type @a _Up
00479        *  @param  __a  An allocator.
00480        *  @param  __p  Pointer to the object to destroy
00481        *
00482        *  Calls @c __a.destroy(__p).
00483       */
00484       template<typename _Up>
00485         static void
00486         destroy(allocator_type& __a, _Up* __p)
00487         { __a.destroy(__p); }
00488 
00489       /**
00490        *  @brief  The maximum supported allocation size
00491        *  @param  __a  An allocator.
00492        *  @return @c __a.max_size()
00493       */
00494       static size_type
00495       max_size(const allocator_type& __a) noexcept
00496       { return __a.max_size(); }
00497 
00498       /**
00499        *  @brief  Obtain an allocator to use when copying a container.
00500        *  @param  __rhs  An allocator.
00501        *  @return @c __rhs
00502       */
00503       static allocator_type
00504       select_on_container_copy_construction(const allocator_type& __rhs)
00505       { return __rhs; }
00506     };
00507 
00508 
00509   template<typename _Alloc>
00510     inline void
00511     __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
00512     { __one = __two; }
00513 
00514   template<typename _Alloc>
00515     inline void
00516     __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
00517     { }
00518 
00519   template<typename _Alloc>
00520     inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
00521     {
00522       typedef allocator_traits<_Alloc> __traits;
00523       typedef typename __traits::propagate_on_container_copy_assignment __pocca;
00524       __do_alloc_on_copy(__one, __two, __pocca());
00525     }
00526 
00527   template<typename _Alloc>
00528     inline _Alloc __alloc_on_copy(const _Alloc& __a)
00529     {
00530       typedef allocator_traits<_Alloc> __traits;
00531       return __traits::select_on_container_copy_construction(__a);
00532     }
00533 
00534   template<typename _Alloc>
00535     inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
00536     { __one = std::move(__two); }
00537 
00538   template<typename _Alloc>
00539     inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
00540     { }
00541 
00542   template<typename _Alloc>
00543     inline void __alloc_on_move(_Alloc& __one, _Alloc& __two)
00544     {
00545       typedef allocator_traits<_Alloc> __traits;
00546       typedef typename __traits::propagate_on_container_move_assignment __pocma;
00547       __do_alloc_on_move(__one, __two, __pocma());
00548     }
00549 
00550   template<typename _Alloc>
00551     inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
00552     {
00553       using std::swap;
00554       swap(__one, __two);
00555     }
00556 
00557   template<typename _Alloc>
00558     inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
00559     { }
00560 
00561   template<typename _Alloc>
00562     inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two)
00563     {
00564       typedef allocator_traits<_Alloc> __traits;
00565       typedef typename __traits::propagate_on_container_swap __pocs;
00566       __do_alloc_on_swap(__one, __two, __pocs());
00567     }
00568 
00569   template<typename _Alloc>
00570     class __is_copy_insertable_impl
00571     {
00572       typedef allocator_traits<_Alloc> _Traits;
00573 
00574       template<typename _Up, typename
00575                = decltype(_Traits::construct(std::declval<_Alloc&>(),
00576                                              std::declval<_Up*>(),
00577                                              std::declval<const _Up&>()))>
00578         static true_type
00579         _M_select(int);
00580 
00581       template<typename _Up>
00582         static false_type
00583         _M_select(...);
00584 
00585     public:
00586       typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
00587     };
00588 
00589   // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
00590   template<typename _Alloc>
00591     struct __is_copy_insertable
00592     : __is_copy_insertable_impl<_Alloc>::type
00593     { };
00594 
00595   // std::allocator<_Tp> just requires CopyConstructible
00596   template<typename _Tp>
00597     struct __is_copy_insertable<allocator<_Tp>>
00598     : is_copy_constructible<_Tp>
00599     { };
00600 
00601 _GLIBCXX_END_NAMESPACE_VERSION
00602 } // namespace std
00603 
00604 #endif
00605 #endif