|
libstdc++
|
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