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