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 <class _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 template<typename _Alloc> 00441 inline void 00442 __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) 00443 { __one = __two; } 00444 00445 template<typename _Alloc> 00446 inline void 00447 __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type) 00448 { } 00449 00450 template<typename _Alloc> 00451 inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two) 00452 { 00453 typedef allocator_traits<_Alloc> __traits; 00454 typedef typename __traits::propagate_on_container_copy_assignment __pocca; 00455 __do_alloc_on_copy(__one, __two, __pocca()); 00456 } 00457 00458 template<typename _Alloc> 00459 inline _Alloc __alloc_on_copy(const _Alloc& __a) 00460 { 00461 typedef allocator_traits<_Alloc> __traits; 00462 return __traits::select_on_container_copy_construction(__a); 00463 } 00464 00465 template<typename _Alloc> 00466 inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type) 00467 { __one = std::move(__two); } 00468 00469 template<typename _Alloc> 00470 inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type) 00471 { } 00472 00473 template<typename _Alloc> 00474 inline void __alloc_on_move(_Alloc& __one, _Alloc& __two) 00475 { 00476 typedef allocator_traits<_Alloc> __traits; 00477 typedef typename __traits::propagate_on_container_move_assignment __pocma; 00478 __do_alloc_on_move(__one, __two, __pocma()); 00479 } 00480 00481 template<typename _Alloc> 00482 inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type) 00483 { 00484 using std::swap; 00485 swap(__one, __two); 00486 } 00487 00488 template<typename _Alloc> 00489 inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type) 00490 { } 00491 00492 template<typename _Alloc> 00493 inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two) 00494 { 00495 typedef allocator_traits<_Alloc> __traits; 00496 typedef typename __traits::propagate_on_container_swap __pocs; 00497 __do_alloc_on_swap(__one, __two, __pocs()); 00498 } 00499 00500 template<typename _Alloc> 00501 class __is_copy_insertable_impl 00502 { 00503 typedef allocator_traits<_Alloc> _Traits; 00504 00505 template<typename _Up, typename 00506 = decltype(_Traits::construct(std::declval<_Alloc&>(), 00507 std::declval<_Up*>(), 00508 std::declval<const _Up&>()))> 00509 static true_type 00510 _M_select(int); 00511 00512 template<typename _Up> 00513 static false_type 00514 _M_select(...); 00515 00516 public: 00517 typedef decltype(_M_select<typename _Alloc::value_type>(0)) type; 00518 }; 00519 00520 // true if _Alloc::value_type is CopyInsertable into containers using _Alloc 00521 template<typename _Alloc> 00522 struct __is_copy_insertable 00523 : __is_copy_insertable_impl<_Alloc>::type 00524 { }; 00525 00526 // std::allocator<_Tp> just requires CopyConstructible 00527 template<typename _Tp> 00528 struct __is_copy_insertable<allocator<_Tp>> 00529 : is_copy_constructible<_Tp> 00530 { }; 00531 00532 _GLIBCXX_END_NAMESPACE_VERSION 00533 } // namespace std 00534 00535 #endif 00536 #endif