1 // Allocator traits -*- C++ -*- 2 3 // Copyright (C) 2011-2014 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file bits/alloc_traits.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{memory} 28 */ 29 30 #ifndef _ALLOC_TRAITS_H 31 #define _ALLOC_TRAITS_H 1 32 33 #if __cplusplus >= 201103L 34 35 #include <bits/memoryfwd.h> 36 #include <bits/ptr_traits.h> 37 #include <ext/numeric_traits.h> 38 39 namespace std _GLIBCXX_VISIBILITY(default) 40 { 41 _GLIBCXX_BEGIN_NAMESPACE_VERSION 42 43 template<typename _Alloc, typename _Tp> 44 class __alloctr_rebind_helper 45 { 46 template<typename _Alloc2, typename _Tp2> 47 static constexpr true_type 48 _S_chk(typename _Alloc2::template rebind<_Tp2>::other*); 49 50 template<typename, typename> 51 static constexpr false_type 52 _S_chk(...); 53 54 public: 55 using __type = decltype(_S_chk<_Alloc, _Tp>(nullptr)); 56 }; 57 58 template<typename _Alloc, typename _Tp, 59 bool = __alloctr_rebind_helper<_Alloc, _Tp>::__type::value> 60 struct __alloctr_rebind; 61 62 template<typename _Alloc, typename _Tp> 63 struct __alloctr_rebind<_Alloc, _Tp, true> 64 { 65 typedef typename _Alloc::template rebind<_Tp>::other __type; 66 }; 67 68 template<template<typename, typename...> class _Alloc, typename _Tp, 69 typename _Up, typename... _Args> 70 struct __alloctr_rebind<_Alloc<_Up, _Args...>, _Tp, false> 71 { 72 typedef _Alloc<_Tp, _Args...> __type; 73 }; 74 75 /** 76 * @brief Uniform interface to all allocator types. 77 * @ingroup allocators 78 */ 79 template<typename _Alloc> 80 struct allocator_traits 81 { 82 /// The allocator type 83 typedef _Alloc allocator_type; 84 /// The allocated type 85 typedef typename _Alloc::value_type value_type; 86 87 #define _GLIBCXX_ALLOC_TR_NESTED_TYPE(_NTYPE, _ALT) \ 88 private: \ 89 template<typename _Tp> \ 90 static typename _Tp::_NTYPE _S_##_NTYPE##_helper(_Tp*); \ 91 static _ALT _S_##_NTYPE##_helper(...); \ 92 typedef decltype(_S_##_NTYPE##_helper((_Alloc*)0)) __##_NTYPE; \ 93 public: 94 95 _GLIBCXX_ALLOC_TR_NESTED_TYPE(pointer, value_type*) 96 97 /** 98 * @brief The allocator's pointer type. 99 * 100 * @c Alloc::pointer if that type exists, otherwise @c value_type* 101 */ 102 typedef __pointer pointer; 103 104 _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_pointer, 105 typename pointer_traits<pointer>::template rebind<const value_type>) 106 107 /** 108 * @brief The allocator's const pointer type. 109 * 110 * @c Alloc::const_pointer if that type exists, otherwise 111 * <tt> pointer_traits<pointer>::rebind<const value_type> </tt> 112 */ 113 typedef __const_pointer const_pointer; 114 115 _GLIBCXX_ALLOC_TR_NESTED_TYPE(void_pointer, 116 typename pointer_traits<pointer>::template rebind<void>) 117 118 /** 119 * @brief The allocator's void pointer type. 120 * 121 * @c Alloc::void_pointer if that type exists, otherwise 122 * <tt> pointer_traits<pointer>::rebind<void> </tt> 123 */ 124 typedef __void_pointer void_pointer; 125 126 _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_void_pointer, 127 typename pointer_traits<pointer>::template rebind<const void>) 128 129 /** 130 * @brief The allocator's const void pointer type. 131 * 132 * @c Alloc::const_void_pointer if that type exists, otherwise 133 * <tt> pointer_traits<pointer>::rebind<const void> </tt> 134 */ 135 typedef __const_void_pointer const_void_pointer; 136 137 _GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type, 138 typename pointer_traits<pointer>::difference_type) 139 140 /** 141 * @brief The allocator's difference type 142 * 143 * @c Alloc::difference_type if that type exists, otherwise 144 * <tt> pointer_traits<pointer>::difference_type </tt> 145 */ 146 typedef __difference_type difference_type; 147 148 _GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type, 149 typename make_unsigned<difference_type>::type) 150 151 /** 152 * @brief The allocator's size type 153 * 154 * @c Alloc::size_type if that type exists, otherwise 155 * <tt> make_unsigned<difference_type>::type </tt> 156 */ 157 typedef __size_type size_type; 158 159 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment, 160 false_type) 161 162 /** 163 * @brief How the allocator is propagated on copy assignment 164 * 165 * @c Alloc::propagate_on_container_copy_assignment if that type exists, 166 * otherwise @c false_type 167 */ 168 typedef __propagate_on_container_copy_assignment 169 propagate_on_container_copy_assignment; 170 171 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment, 172 false_type) 173 174 /** 175 * @brief How the allocator is propagated on move assignment 176 * 177 * @c Alloc::propagate_on_container_move_assignment if that type exists, 178 * otherwise @c false_type 179 */ 180 typedef __propagate_on_container_move_assignment 181 propagate_on_container_move_assignment; 182 183 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, 184 false_type) 185 186 /** 187 * @brief How the allocator is propagated on swap 188 * 189 * @c Alloc::propagate_on_container_swap if that type exists, 190 * otherwise @c false_type 191 */ 192 typedef __propagate_on_container_swap propagate_on_container_swap; 193 194 #undef _GLIBCXX_ALLOC_TR_NESTED_TYPE 195 196 template<typename _Tp> 197 using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type; 198 template<typename _Tp> 199 using rebind_traits = allocator_traits<rebind_alloc<_Tp>>; 200 201 private: 202 template<typename _Alloc2> 203 struct __allocate_helper 204 { 205 template<typename _Alloc3, 206 typename = decltype(std::declval<_Alloc3*>()->allocate( 207 std::declval<size_type>(), 208 std::declval<const_void_pointer>()))> 209 static true_type __test(int); 210 211 template<typename> 212 static false_type __test(...); 213 214 using type = decltype(__test<_Alloc>(0)); 215 }; 216 217 template<typename _Alloc2> 218 using __has_allocate = typename __allocate_helper<_Alloc2>::type; 219 220 template<typename _Alloc2, 221 typename = _Require<__has_allocate<_Alloc2>>> 222 static pointer 223 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint) 224 { return __a.allocate(__n, __hint); } 225 226 template<typename _Alloc2, typename _UnusedHint, 227 typename = _Require<__not_<__has_allocate<_Alloc2>>>> 228 static pointer 229 _S_allocate(_Alloc2& __a, size_type __n, _UnusedHint) 230 { return __a.allocate(__n); } 231 232 template<typename _Tp, typename... _Args> 233 struct __construct_helper 234 { 235 template<typename _Alloc2, 236 typename = decltype(std::declval<_Alloc2*>()->construct( 237 std::declval<_Tp*>(), std::declval<_Args>()...))> 238 static true_type __test(int); 239 240 template<typename> 241 static false_type __test(...); 242 243 using type = decltype(__test<_Alloc>(0)); 244 }; 245 246 template<typename _Tp, typename... _Args> 247 using __has_construct 248 = typename __construct_helper<_Tp, _Args...>::type; 249 250 template<typename _Tp, typename... _Args> 251 static _Require<__has_construct<_Tp, _Args...>> 252 _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args) 253 { __a.construct(__p, std::forward<_Args>(__args)...); } 254 255 template<typename _Tp, typename... _Args> 256 static 257 _Require<__and_<__not_<__has_construct<_Tp, _Args...>>, 258 is_constructible<_Tp, _Args...>>> 259 _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) 260 { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); } 261 262 template<typename _Tp> 263 struct __destroy_helper 264 { 265 template<typename _Alloc2, 266 typename = decltype(std::declval<_Alloc2*>()->destroy( 267 std::declval<_Tp*>()))> 268 static true_type __test(int); 269 270 template<typename> 271 static false_type __test(...); 272 273 using type = decltype(__test<_Alloc>(0)); 274 }; 275 276 template<typename _Tp> 277 using __has_destroy = typename __destroy_helper<_Tp>::type; 278 279 template<typename _Tp> 280 static _Require<__has_destroy<_Tp>> 281 _S_destroy(_Alloc& __a, _Tp* __p) 282 { __a.destroy(__p); } 283 284 template<typename _Tp> 285 static _Require<__not_<__has_destroy<_Tp>>> 286 _S_destroy(_Alloc&, _Tp* __p) 287 { __p->~_Tp(); } 288 289 template<typename _Alloc2> 290 struct __maxsize_helper 291 { 292 template<typename _Alloc3, 293 typename = decltype(std::declval<_Alloc3*>()->max_size())> 294 static true_type __test(int); 295 296 template<typename> 297 static false_type __test(...); 298 299 using type = decltype(__test<_Alloc2>(0)); 300 }; 301 302 template<typename _Alloc2> 303 using __has_max_size = typename __maxsize_helper<_Alloc2>::type; 304 305 template<typename _Alloc2, 306 typename = _Require<__has_max_size<_Alloc2>>> 307 static size_type 308 _S_max_size(_Alloc2& __a, int) 309 { return __a.max_size(); } 310 311 template<typename _Alloc2, 312 typename = _Require<__not_<__has_max_size<_Alloc2>>>> 313 static size_type 314 _S_max_size(_Alloc2&, ...) 315 { return __gnu_cxx::__numeric_traits<size_type>::__max; } 316 317 template<typename _Alloc2> 318 struct __select_helper 319 { 320 template<typename _Alloc3, typename 321 = decltype(std::declval<_Alloc3*>() 322 ->select_on_container_copy_construction())> 323 static true_type __test(int); 324 325 template<typename> 326 static false_type __test(...); 327 328 using type = decltype(__test<_Alloc2>(0)); 329 }; 330 331 template<typename _Alloc2> 332 using __has_soccc = typename __select_helper<_Alloc2>::type; 333 334 template<typename _Alloc2, 335 typename = _Require<__has_soccc<_Alloc2>>> 336 static _Alloc2 337 _S_select(_Alloc2& __a, int) 338 { return __a.select_on_container_copy_construction(); } 339 340 template<typename _Alloc2, 341 typename = _Require<__not_<__has_soccc<_Alloc2>>>> 342 static _Alloc2 343 _S_select(_Alloc2& __a, ...) 344 { return __a; } 345 346 public: 347 348 /** 349 * @brief Allocate memory. 350 * @param __a An allocator. 351 * @param __n The number of objects to allocate space for. 352 * 353 * Calls @c a.allocate(n) 354 */ 355 static pointer 356 allocate(_Alloc& __a, size_type __n) 357 { return __a.allocate(__n); } 358 359 /** 360 * @brief Allocate memory. 361 * @param __a An allocator. 362 * @param __n The number of objects to allocate space for. 363 * @param __hint Aid to locality. 364 * @return Memory of suitable size and alignment for @a n objects 365 * of type @c value_type 366 * 367 * Returns <tt> a.allocate(n, hint) </tt> if that expression is 368 * well-formed, otherwise returns @c a.allocate(n) 369 */ 370 static pointer 371 allocate(_Alloc& __a, size_type __n, const_void_pointer __hint) 372 { return _S_allocate(__a, __n, __hint); } 373 374 /** 375 * @brief Deallocate memory. 376 * @param __a An allocator. 377 * @param __p Pointer to the memory to deallocate. 378 * @param __n The number of objects space was allocated for. 379 * 380 * Calls <tt> a.deallocate(p, n) </tt> 381 */ 382 static void deallocate(_Alloc& __a, pointer __p, size_type __n) 383 { __a.deallocate(__p, __n); } 384 385 /** 386 * @brief Construct an object of type @a _Tp 387 * @param __a An allocator. 388 * @param __p Pointer to memory of suitable size and alignment for Tp 389 * @param __args Constructor arguments. 390 * 391 * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt> 392 * if that expression is well-formed, otherwise uses placement-new 393 * to construct an object of type @a _Tp at location @a __p from the 394 * arguments @a __args... 395 */ 396 template<typename _Tp, typename... _Args> 397 static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args) 398 -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...)) 399 { _S_construct(__a, __p, std::forward<_Args>(__args)...); } 400 401 /** 402 * @brief Destroy an object of type @a _Tp 403 * @param __a An allocator. 404 * @param __p Pointer to the object to destroy 405 * 406 * Calls @c __a.destroy(__p) if that expression is well-formed, 407 * otherwise calls @c __p->~_Tp() 408 */ 409 template <class _Tp> 410 static void destroy(_Alloc& __a, _Tp* __p) 411 { _S_destroy(__a, __p); } 412 413 /** 414 * @brief The maximum supported allocation size 415 * @param __a An allocator. 416 * @return @c __a.max_size() or @c numeric_limits<size_type>::max() 417 * 418 * Returns @c __a.max_size() if that expression is well-formed, 419 * otherwise returns @c numeric_limits<size_type>::max() 420 */ 421 static size_type max_size(const _Alloc& __a) noexcept 422 { return _S_max_size(__a, 0); } 423 424 /** 425 * @brief Obtain an allocator to use when copying a container. 426 * @param __rhs An allocator. 427 * @return @c __rhs.select_on_container_copy_construction() or @a __rhs 428 * 429 * Returns @c __rhs.select_on_container_copy_construction() if that 430 * expression is well-formed, otherwise returns @a __rhs 431 */ 432 static _Alloc 433 select_on_container_copy_construction(const _Alloc& __rhs) 434 { return _S_select(__rhs, 0); } 435 }; 436 437 template<typename _Alloc> 438 inline void 439 __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) 440 { __one = __two; } 441 442 template<typename _Alloc> 443 inline void 444 __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type) 445 { } 446 447 template<typename _Alloc> 448 inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two) 449 { 450 typedef allocator_traits<_Alloc> __traits; 451 typedef typename __traits::propagate_on_container_copy_assignment __pocca; 452 __do_alloc_on_copy(__one, __two, __pocca()); 453 } 454 455 template<typename _Alloc> 456 inline _Alloc __alloc_on_copy(const _Alloc& __a) 457 { 458 typedef allocator_traits<_Alloc> __traits; 459 return __traits::select_on_container_copy_construction(__a); 460 } 461 462 template<typename _Alloc> 463 inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type) 464 { __one = std::move(__two); } 465 466 template<typename _Alloc> 467 inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type) 468 { } 469 470 template<typename _Alloc> 471 inline void __alloc_on_move(_Alloc& __one, _Alloc& __two) 472 { 473 typedef allocator_traits<_Alloc> __traits; 474 typedef typename __traits::propagate_on_container_move_assignment __pocma; 475 __do_alloc_on_move(__one, __two, __pocma()); 476 } 477 478 template<typename _Alloc> 479 inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type) 480 { 481 using std::swap; 482 swap(__one, __two); 483 } 484 485 template<typename _Alloc> 486 inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type) 487 { } 488 489 template<typename _Alloc> 490 inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two) 491 { 492 typedef allocator_traits<_Alloc> __traits; 493 typedef typename __traits::propagate_on_container_swap __pocs; 494 __do_alloc_on_swap(__one, __two, __pocs()); 495 } 496 497 template<typename _Alloc> 498 class __is_copy_insertable_impl 499 { 500 typedef allocator_traits<_Alloc> _Traits; 501 502 template<typename _Up, typename 503 = decltype(_Traits::construct(std::declval<_Alloc&>(), 504 std::declval<_Up*>(), 505 std::declval<const _Up&>()))> 506 static true_type 507 _M_select(int); 508 509 template<typename _Up> 510 static false_type 511 _M_select(...); 512 513 public: 514 typedef decltype(_M_select<typename _Alloc::value_type>(0)) type; 515 }; 516 517 // true if _Alloc::value_type is CopyInsertable into containers using _Alloc 518 template<typename _Alloc> 519 struct __is_copy_insertable 520 : __is_copy_insertable_impl<_Alloc>::type 521 { }; 522 523 // std::allocator<_Tp> just requires CopyConstructible 524 template<typename _Tp> 525 struct __is_copy_insertable<allocator<_Tp>> 526 : is_copy_constructible<_Tp> 527 { }; 528 529 _GLIBCXX_END_NAMESPACE_VERSION 530 } // namespace std 531 532 #endif 533 #endif 534