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