libstdc++
bits/alloc_traits.h
Go to the documentation of this file.
00001 // Allocator traits -*- C++ -*-
00002 
00003 // Copyright (C) 2011, 2012, 2013 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 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00034 
00035 #include <bits/ptr_traits.h>
00036 #include <ext/numeric_traits.h>
00037 
00038 namespace std _GLIBCXX_VISIBILITY(default)
00039 {
00040 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00041 
00042   template<typename _Tp>
00043     class allocator;
00044 
00045   template<typename _Alloc, typename _Tp>
00046     class __alloctr_rebind_helper
00047     {
00048       template<typename _Alloc2, typename _Tp2>
00049     static constexpr bool
00050         _S_chk(typename _Alloc2::template rebind<_Tp2>::other*)
00051     { return true; }
00052 
00053       template<typename, typename>
00054         static constexpr bool
00055         _S_chk(...)
00056         { return false; }
00057 
00058     public:
00059       static const bool __value = _S_chk<_Alloc, _Tp>(nullptr);
00060     };
00061 
00062   template<typename _Alloc, typename _Tp>
00063     const bool __alloctr_rebind_helper<_Alloc, _Tp>::__value;
00064 
00065   template<typename _Alloc, typename _Tp,
00066            bool = __alloctr_rebind_helper<_Alloc, _Tp>::__value>
00067     struct __alloctr_rebind;
00068 
00069   template<typename _Alloc, typename _Tp>
00070     struct __alloctr_rebind<_Alloc, _Tp, true>
00071     {
00072       typedef typename _Alloc::template rebind<_Tp>::other __type;
00073     };
00074 
00075   template<template<typename, typename...> class _Alloc, typename _Tp,
00076             typename _Up, typename... _Args>
00077     struct __alloctr_rebind<_Alloc<_Up, _Args...>, _Tp, false>
00078     {
00079       typedef _Alloc<_Tp, _Args...> __type;
00080     };
00081 
00082   /**
00083    * @brief  Uniform interface to all allocator types.
00084    * @ingroup allocators
00085   */
00086   template<typename _Alloc>
00087     struct allocator_traits
00088     {
00089       /// The allocator type
00090       typedef _Alloc allocator_type;
00091       /// The allocated type
00092       typedef typename _Alloc::value_type value_type;
00093 
00094 #define _GLIBCXX_ALLOC_TR_NESTED_TYPE(_NTYPE, _ALT) \
00095   private: \
00096   template<typename _Tp> \
00097     static typename _Tp::_NTYPE _S_##_NTYPE##_helper(_Tp*); \
00098   static _ALT _S_##_NTYPE##_helper(...); \
00099     typedef decltype(_S_##_NTYPE##_helper((_Alloc*)0)) __##_NTYPE; \
00100   public:
00101 
00102 _GLIBCXX_ALLOC_TR_NESTED_TYPE(pointer, value_type*)
00103 
00104       /**
00105        * @brief   The allocator's pointer type.
00106        *
00107        * @c Alloc::pointer if that type exists, otherwise @c value_type*
00108       */
00109       typedef __pointer pointer;
00110 
00111 _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_pointer,
00112   typename pointer_traits<pointer>::template rebind<const value_type>)
00113 
00114       /**
00115        * @brief   The allocator's const pointer type.
00116        *
00117        * @c Alloc::const_pointer if that type exists, otherwise
00118        * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
00119       */
00120       typedef __const_pointer const_pointer;
00121 
00122 _GLIBCXX_ALLOC_TR_NESTED_TYPE(void_pointer,
00123   typename pointer_traits<pointer>::template rebind<void>)
00124 
00125       /**
00126        * @brief   The allocator's void pointer type.
00127        *
00128        * @c Alloc::void_pointer if that type exists, otherwise
00129        * <tt> pointer_traits<pointer>::rebind<void> </tt>
00130       */
00131       typedef __void_pointer void_pointer;
00132 
00133 _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_void_pointer,
00134   typename pointer_traits<pointer>::template rebind<const void>)
00135 
00136       /**
00137        * @brief   The allocator's const void pointer type.
00138        *
00139        * @c Alloc::const_void_pointer if that type exists, otherwise
00140        * <tt> pointer_traits<pointer>::rebind<const void> </tt>
00141       */
00142       typedef __const_void_pointer const_void_pointer;
00143 
00144 _GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type,
00145                               typename pointer_traits<pointer>::difference_type)
00146 
00147       /**
00148        * @brief   The allocator's difference type
00149        *
00150        * @c Alloc::difference_type if that type exists, otherwise
00151        * <tt> pointer_traits<pointer>::difference_type </tt>
00152       */
00153       typedef __difference_type difference_type;
00154 
00155 _GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type,
00156                               typename make_unsigned<difference_type>::type)
00157 
00158       /**
00159        * @brief   The allocator's size type
00160        *
00161        * @c Alloc::size_type if that type exists, otherwise
00162        * <tt> make_unsigned<difference_type>::type </tt>
00163       */
00164       typedef __size_type size_type;
00165 
00166 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment,
00167                               false_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       typedef __propagate_on_container_copy_assignment
00176         propagate_on_container_copy_assignment;
00177 
00178 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment,
00179                               false_type)
00180 
00181       /**
00182        * @brief   How the allocator is propagated on move assignment
00183        *
00184        * @c Alloc::propagate_on_container_move_assignment if that type exists,
00185        * otherwise @c false_type
00186       */
00187       typedef __propagate_on_container_move_assignment
00188         propagate_on_container_move_assignment;
00189 
00190 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
00191                               false_type)
00192 
00193       /**
00194        * @brief   How the allocator is propagated on swap
00195        *
00196        * @c Alloc::propagate_on_container_swap if that type exists,
00197        * otherwise @c false_type
00198       */
00199       typedef __propagate_on_container_swap propagate_on_container_swap;
00200 
00201 #undef _GLIBCXX_ALLOC_TR_NESTED_TYPE
00202 
00203       template<typename _Tp>
00204         using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;
00205       template<typename _Tp>
00206         using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
00207 
00208     private:
00209       template<typename _Alloc2>
00210     struct __allocate_helper
00211     {
00212       template<typename _Alloc3,
00213         typename = decltype(std::declval<_Alloc3*>()->allocate(
00214           std::declval<size_type>(),
00215           std::declval<const_void_pointer>()))>
00216         static true_type __test(int);
00217 
00218       template<typename>
00219         static false_type __test(...);
00220 
00221       typedef decltype(__test<_Alloc>(0)) type;
00222       static const bool value = type::value;
00223     };
00224 
00225       template<typename _Alloc2>
00226     static typename
00227         enable_if<__allocate_helper<_Alloc2>::value, pointer>::type
00228         _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint)
00229     { return __a.allocate(__n, __hint); }
00230 
00231       template<typename _Alloc2>
00232     static typename
00233         enable_if<!__allocate_helper<_Alloc2>::value, pointer>::type
00234         _S_allocate(_Alloc2& __a, size_type __n, ...)
00235     { return __a.allocate(__n); }
00236 
00237       template<typename _Tp, typename... _Args>
00238     struct __construct_helper
00239     {
00240       template<typename _Alloc2,
00241         typename = decltype(std::declval<_Alloc2*>()->construct(
00242           std::declval<_Tp*>(), std::declval<_Args>()...))>
00243         static true_type __test(int);
00244 
00245       template<typename>
00246         static false_type __test(...);
00247 
00248       typedef decltype(__test<_Alloc>(0)) type;
00249       static const bool value = type::value;
00250     };
00251 
00252       template<typename _Tp, typename... _Args>
00253     static typename
00254         enable_if<__construct_helper<_Tp, _Args...>::value, void>::type
00255         _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
00256     { __a.construct(__p, std::forward<_Args>(__args)...); }
00257 
00258       template<typename _Tp, typename... _Args>
00259     static typename
00260     enable_if<__and_<__not_<__construct_helper<_Tp, _Args...>>,
00261              is_constructible<_Tp, _Args...>>::value, void>::type
00262         _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
00263     { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
00264 
00265       template<typename _Tp>
00266     struct __destroy_helper
00267     {
00268       template<typename _Alloc2,
00269         typename = decltype(std::declval<_Alloc2*>()->destroy(
00270           std::declval<_Tp*>()))>
00271         static true_type __test(int);
00272 
00273       template<typename>
00274         static false_type __test(...);
00275 
00276       typedef decltype(__test<_Alloc>(0)) type;
00277       static const bool value = type::value;
00278     };
00279 
00280       template<typename _Tp>
00281     static typename enable_if<__destroy_helper<_Tp>::value, void>::type
00282         _S_destroy(_Alloc& __a, _Tp* __p)
00283     { __a.destroy(__p); }
00284 
00285       template<typename _Tp>
00286     static typename enable_if<!__destroy_helper<_Tp>::value, void>::type
00287         _S_destroy(_Alloc&, _Tp* __p)
00288     { __p->~_Tp(); }
00289 
00290       template<typename _Alloc2>
00291     struct __maxsize_helper
00292     {
00293       template<typename _Alloc3,
00294         typename = decltype(std::declval<_Alloc3*>()->max_size())>
00295         static true_type __test(int);
00296 
00297       template<typename>
00298         static false_type __test(...);
00299 
00300       typedef decltype(__test<_Alloc2>(0)) type;
00301       static const bool value = type::value;
00302     };
00303 
00304       template<typename _Alloc2>
00305     static typename
00306         enable_if<__maxsize_helper<_Alloc2>::value, size_type>::type
00307         _S_max_size(_Alloc2& __a)
00308     { return __a.max_size(); }
00309 
00310       template<typename _Alloc2>
00311     static typename
00312         enable_if<!__maxsize_helper<_Alloc2>::value, size_type>::type
00313     _S_max_size(_Alloc2&)
00314     { return __gnu_cxx::__numeric_traits<size_type>::__max; }
00315 
00316       template<typename _Alloc2>
00317     struct __select_helper
00318     {
00319       template<typename _Alloc3, typename
00320         = decltype(std::declval<_Alloc3*>()
00321         ->select_on_container_copy_construction())>
00322         static true_type __test(int);
00323 
00324       template<typename>
00325         static false_type __test(...);
00326 
00327       typedef decltype(__test<_Alloc2>(0)) type;
00328       static const bool value = type::value;
00329     };
00330       template<typename _Alloc2>
00331     static typename
00332         enable_if<__select_helper<_Alloc2>::value, _Alloc2>::type
00333         _S_select(_Alloc2& __a)
00334     { return __a.select_on_container_copy_construction(); }
00335 
00336       template<typename _Alloc2>
00337     static typename
00338         enable_if<!__select_helper<_Alloc2>::value, _Alloc2>::type
00339         _S_select(_Alloc2& __a)
00340     { return __a; }
00341 
00342     public:
00343 
00344       /**
00345        *  @brief  Allocate memory.
00346        *  @param  __a  An allocator.
00347        *  @param  __n  The number of objects to allocate space for.
00348        *
00349        *  Calls @c a.allocate(n)
00350       */
00351       static pointer
00352       allocate(_Alloc& __a, size_type __n)
00353       { return __a.allocate(__n); }
00354 
00355       /**
00356        *  @brief  Allocate memory.
00357        *  @param  __a  An allocator.
00358        *  @param  __n  The number of objects to allocate space for.
00359        *  @param  __hint Aid to locality.
00360        *  @return Memory of suitable size and alignment for @a n objects
00361        *          of type @c value_type
00362        *
00363        *  Returns <tt> a.allocate(n, hint) </tt> if that expression is
00364        *  well-formed, otherwise returns @c a.allocate(n)
00365       */
00366       static pointer
00367       allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
00368       { return _S_allocate(__a, __n, __hint); }
00369 
00370       /**
00371        *  @brief  Deallocate memory.
00372        *  @param  __a  An allocator.
00373        *  @param  __p  Pointer to the memory to deallocate.
00374        *  @param  __n  The number of objects space was allocated for.
00375        *
00376        *  Calls <tt> a.deallocate(p, n) </tt>
00377       */
00378       static void deallocate(_Alloc& __a, pointer __p, size_type __n)
00379       { __a.deallocate(__p, __n); }
00380 
00381       /**
00382        *  @brief  Construct an object of type @a _Tp
00383        *  @param  __a  An allocator.
00384        *  @param  __p  Pointer to memory of suitable size and alignment for Tp
00385        *  @param  __args Constructor arguments.
00386        *
00387        *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
00388        *  if that expression is well-formed, otherwise uses placement-new
00389        *  to construct an object of type @a _Tp at location @a __p from the
00390        *  arguments @a __args...
00391       */
00392       template<typename _Tp, typename... _Args>
00393     static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
00394     -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
00395     { _S_construct(__a, __p, std::forward<_Args>(__args)...); }
00396 
00397       /**
00398        *  @brief  Destroy an object of type @a _Tp
00399        *  @param  __a  An allocator.
00400        *  @param  __p  Pointer to the object to destroy
00401        *
00402        *  Calls @c __a.destroy(__p) if that expression is well-formed,
00403        *  otherwise calls @c __p->~_Tp()
00404       */
00405       template <class _Tp>
00406     static void destroy(_Alloc& __a, _Tp* __p)
00407     { _S_destroy(__a, __p); }
00408 
00409       /**
00410        *  @brief  The maximum supported allocation size
00411        *  @param  __a  An allocator.
00412        *  @return @c __a.max_size() or @c numeric_limits<size_type>::max()
00413        *
00414        *  Returns @c __a.max_size() if that expression is well-formed,
00415        *  otherwise returns @c numeric_limits<size_type>::max()
00416       */
00417       static size_type max_size(const _Alloc& __a)
00418       { return _S_max_size(__a); }
00419 
00420       /**
00421        *  @brief  Obtain an allocator to use when copying a container.
00422        *  @param  __rhs  An allocator.
00423        *  @return @c __rhs.select_on_container_copy_construction() or @a __rhs
00424        *
00425        *  Returns @c __rhs.select_on_container_copy_construction() if that
00426        *  expression is well-formed, otherwise returns @a __rhs
00427       */
00428       static _Alloc
00429       select_on_container_copy_construction(const _Alloc& __rhs)
00430       { return _S_select(__rhs); }
00431     };
00432 
00433   template<typename _Alloc>
00434   template<typename _Alloc2>
00435     const bool allocator_traits<_Alloc>::__allocate_helper<_Alloc2>::value;
00436 
00437   template<typename _Alloc>
00438   template<typename _Tp, typename... _Args>
00439     const bool
00440     allocator_traits<_Alloc>::__construct_helper<_Tp, _Args...>::value;
00441 
00442   template<typename _Alloc>
00443   template<typename _Tp>
00444     const bool allocator_traits<_Alloc>::__destroy_helper<_Tp>::value;
00445 
00446   template<typename _Alloc>
00447   template<typename _Alloc2>
00448     const bool allocator_traits<_Alloc>::__maxsize_helper<_Alloc2>::value;
00449 
00450   template<typename _Alloc>
00451   template<typename _Alloc2>
00452     const bool allocator_traits<_Alloc>::__select_helper<_Alloc2>::value;
00453 
00454   template<typename _Alloc>
00455     inline void
00456     __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
00457     { __one = __two; }
00458 
00459   template<typename _Alloc>
00460     inline void
00461     __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
00462     { }
00463 
00464   template<typename _Alloc>
00465     inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
00466     {
00467       typedef allocator_traits<_Alloc> __traits;
00468       typedef typename __traits::propagate_on_container_copy_assignment __pocca;
00469       __do_alloc_on_copy(__one, __two, __pocca());
00470     }
00471 
00472   template<typename _Alloc>
00473     inline _Alloc __alloc_on_copy(const _Alloc& __a)
00474     {
00475       typedef allocator_traits<_Alloc> __traits;
00476       return __traits::select_on_container_copy_construction(__a);
00477     }
00478 
00479   template<typename _Alloc>
00480     inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
00481     { __one = std::move(__two); }
00482 
00483   template<typename _Alloc>
00484     inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
00485     { }
00486 
00487   template<typename _Alloc>
00488     inline void __alloc_on_move(_Alloc& __one, _Alloc& __two)
00489     {
00490       typedef allocator_traits<_Alloc> __traits;
00491       typedef typename __traits::propagate_on_container_move_assignment __pocma;
00492       __do_alloc_on_move(__one, __two, __pocma());
00493     }
00494 
00495   template<typename _Alloc>
00496     inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
00497     {
00498       using std::swap;
00499       swap(__one, __two);
00500     }
00501 
00502   template<typename _Alloc>
00503     inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
00504     { }
00505 
00506   template<typename _Alloc>
00507     inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two)
00508     {
00509       typedef allocator_traits<_Alloc> __traits;
00510       typedef typename __traits::propagate_on_container_swap __pocs;
00511       __do_alloc_on_swap(__one, __two, __pocs());
00512     }
00513 
00514   template<typename _Alloc>
00515     class __is_copy_insertable_impl
00516     {
00517       typedef allocator_traits<_Alloc> _Traits;
00518 
00519       template<typename _Up, typename
00520            = decltype(_Traits::construct(std::declval<_Alloc&>(),
00521                          std::declval<_Up*>(),
00522                          std::declval<const _Up&>()))>
00523     static true_type
00524     _M_select(int);
00525 
00526       template<typename _Up>
00527     static false_type
00528     _M_select(...);
00529 
00530     public:
00531       typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
00532     };
00533 
00534   // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
00535   template<typename _Alloc>
00536     struct __is_copy_insertable
00537     : __is_copy_insertable_impl<_Alloc>::type
00538     { };
00539 
00540   // std::allocator<_Tp> just requires CopyConstructible
00541   template<typename _Tp>
00542     struct __is_copy_insertable<allocator<_Tp>>
00543     : is_copy_constructible<_Tp>
00544     { };
00545 
00546   // Used to allow copy construction of unordered containers
00547   template<bool> struct __allow_copy_cons { };
00548 
00549   // Used to delete copy constructor of unordered containers
00550   template<>
00551     struct __allow_copy_cons<false>
00552     {
00553       __allow_copy_cons() = default;
00554       __allow_copy_cons(const __allow_copy_cons&) = delete;
00555       __allow_copy_cons(__allow_copy_cons&&) = default;
00556       __allow_copy_cons& operator=(const __allow_copy_cons&) = default;
00557       __allow_copy_cons& operator=(__allow_copy_cons&&) = default;
00558     };
00559 
00560   template<typename _Alloc>
00561     using __check_copy_constructible
00562       = __allow_copy_cons<__is_copy_insertable<_Alloc>::value>;
00563 
00564 _GLIBCXX_END_NAMESPACE_VERSION
00565 } // namespace std
00566 
00567 #endif
00568 #endif