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