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