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