1 // Allocator traits -*- C++ -*- 2 3 // Copyright (C) 2011, 2012 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 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 34 35 #include <bits/ptr_traits.h> 36 #include <ext/numeric_traits.h> 37 38 namespace std _GLIBCXX_VISIBILITY(default) 39 { 40 _GLIBCXX_BEGIN_NAMESPACE_VERSION 41 42 template<typename _Alloc, typename _Tp> 43 class __alloctr_rebind_helper 44 { 45 template<typename _Alloc2, typename _Tp2> 46 static constexpr bool 47 _S_chk(typename _Alloc2::template rebind<_Tp2>::other*) 48 { return true; } 49 50 template<typename, typename> 51 static constexpr bool 52 _S_chk(...) 53 { return false; } 54 55 public: 56 static const bool __value = _S_chk<_Alloc, _Tp>(nullptr); 57 }; 58 59 template<typename _Alloc, typename _Tp> 60 const bool __alloctr_rebind_helper<_Alloc, _Tp>::__value; 61 62 template<typename _Alloc, typename _Tp, 63 bool = __alloctr_rebind_helper<_Alloc, _Tp>::__value> 64 struct __alloctr_rebind; 65 66 template<typename _Alloc, typename _Tp> 67 struct __alloctr_rebind<_Alloc, _Tp, true> 68 { 69 typedef typename _Alloc::template rebind<_Tp>::other __type; 70 }; 71 72 template<template<typename, typename...> class _Alloc, typename _Tp, 73 typename _Up, typename... _Args> 74 struct __alloctr_rebind<_Alloc<_Up, _Args...>, _Tp, false> 75 { 76 typedef _Alloc<_Tp, _Args...> __type; 77 }; 78 79 /** 80 * @brief Uniform interface to all allocator types. 81 * @ingroup allocators 82 */ 83 template<typename _Alloc> 84 struct allocator_traits 85 { 86 /// The allocator type 87 typedef _Alloc allocator_type; 88 /// The allocated type 89 typedef typename _Alloc::value_type value_type; 90 91 #define _GLIBCXX_ALLOC_TR_NESTED_TYPE(_NTYPE, _ALT) \ 92 private: \ 93 template<typename _Tp> \ 94 static typename _Tp::_NTYPE _S_##_NTYPE##_helper(_Tp*); \ 95 static _ALT _S_##_NTYPE##_helper(...); \ 96 typedef decltype(_S_##_NTYPE##_helper((_Alloc*)0)) __##_NTYPE; \ 97 public: 98 99 _GLIBCXX_ALLOC_TR_NESTED_TYPE(pointer, value_type*) 100 101 /** 102 * @brief The allocator's pointer type. 103 * 104 * @c Alloc::pointer if that type exists, otherwise @c value_type* 105 */ 106 typedef __pointer pointer; 107 108 _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_pointer, 109 typename pointer_traits<pointer>::template rebind<const value_type>) 110 111 /** 112 * @brief The allocator's const pointer type. 113 * 114 * @c Alloc::const_pointer if that type exists, otherwise 115 * <tt> pointer_traits<pointer>::rebind<const value_type> </tt> 116 */ 117 typedef __const_pointer const_pointer; 118 119 _GLIBCXX_ALLOC_TR_NESTED_TYPE(void_pointer, 120 typename pointer_traits<pointer>::template rebind<void>) 121 122 /** 123 * @brief The allocator's void pointer type. 124 * 125 * @c Alloc::void_pointer if that type exists, otherwise 126 * <tt> pointer_traits<pointer>::rebind<void> </tt> 127 */ 128 typedef __void_pointer void_pointer; 129 130 _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_void_pointer, 131 typename pointer_traits<pointer>::template rebind<const void>) 132 133 /** 134 * @brief The allocator's const void pointer type. 135 * 136 * @c Alloc::const_void_pointer if that type exists, otherwise 137 * <tt> pointer_traits<pointer>::rebind<const void> </tt> 138 */ 139 typedef __const_void_pointer const_void_pointer; 140 141 _GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type, 142 typename pointer_traits<pointer>::difference_type) 143 144 /** 145 * @brief The allocator's difference type 146 * 147 * @c Alloc::difference_type if that type exists, otherwise 148 * <tt> pointer_traits<pointer>::difference_type </tt> 149 */ 150 typedef __difference_type difference_type; 151 152 _GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type, 153 typename make_unsigned<difference_type>::type) 154 155 /** 156 * @brief The allocator's size type 157 * 158 * @c Alloc::size_type if that type exists, otherwise 159 * <tt> make_unsigned<difference_type>::type </tt> 160 */ 161 typedef __size_type size_type; 162 163 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment, 164 false_type) 165 166 /** 167 * @brief How the allocator is propagated on copy assignment 168 * 169 * @c Alloc::propagate_on_container_copy_assignment if that type exists, 170 * otherwise @c false_type 171 */ 172 typedef __propagate_on_container_copy_assignment 173 propagate_on_container_copy_assignment; 174 175 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment, 176 false_type) 177 178 /** 179 * @brief How the allocator is propagated on move assignment 180 * 181 * @c Alloc::propagate_on_container_move_assignment if that type exists, 182 * otherwise @c false_type 183 */ 184 typedef __propagate_on_container_move_assignment 185 propagate_on_container_move_assignment; 186 187 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, 188 false_type) 189 190 /** 191 * @brief How the allocator is propagated on swap 192 * 193 * @c Alloc::propagate_on_container_swap if that type exists, 194 * otherwise @c false_type 195 */ 196 typedef __propagate_on_container_swap propagate_on_container_swap; 197 198 #undef _GLIBCXX_ALLOC_TR_NESTED_TYPE 199 200 template<typename _Tp> 201 using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type; 202 template<typename _Tp> 203 using rebind_traits = allocator_traits<rebind_alloc<_Tp>>; 204 205 private: 206 template<typename _Alloc2> 207 struct __allocate_helper 208 { 209 template<typename _Alloc3, 210 typename = decltype(std::declval<_Alloc3*>()->allocate( 211 std::declval<size_type>(), 212 std::declval<const_void_pointer>()))> 213 static true_type __test(int); 214 215 template<typename> 216 static false_type __test(...); 217 218 typedef decltype(__test<_Alloc>(0)) type; 219 static const bool value = type::value; 220 }; 221 222 template<typename _Alloc2> 223 static typename 224 enable_if<__allocate_helper<_Alloc2>::value, pointer>::type 225 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint) 226 { return __a.allocate(__n, __hint); } 227 228 template<typename _Alloc2> 229 static typename 230 enable_if<!__allocate_helper<_Alloc2>::value, pointer>::type 231 _S_allocate(_Alloc2& __a, size_type __n, ...) 232 { return __a.allocate(__n); } 233 234 template<typename _Tp, typename... _Args> 235 struct __construct_helper 236 { 237 template<typename _Alloc2, 238 typename = decltype(std::declval<_Alloc2*>()->construct( 239 std::declval<_Tp*>(), std::declval<_Args>()...))> 240 static true_type __test(int); 241 242 template<typename> 243 static false_type __test(...); 244 245 typedef decltype(__test<_Alloc>(0)) type; 246 static const bool value = type::value; 247 }; 248 249 template<typename _Tp, typename... _Args> 250 static typename 251 enable_if<__construct_helper<_Tp, _Args...>::value, void>::type 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 typename 257 enable_if<!__construct_helper<_Tp, _Args...>::value, void>::type 258 _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) 259 { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); } 260 261 template<typename _Tp> 262 struct __destroy_helper 263 { 264 template<typename _Alloc2, 265 typename = decltype(std::declval<_Alloc2*>()->destroy( 266 std::declval<_Tp*>()))> 267 static true_type __test(int); 268 269 template<typename> 270 static false_type __test(...); 271 272 typedef decltype(__test<_Alloc>(0)) type; 273 static const bool value = type::value; 274 }; 275 276 template<typename _Tp> 277 static typename enable_if<__destroy_helper<_Tp>::value, void>::type 278 _S_destroy(_Alloc& __a, _Tp* __p) 279 { __a.destroy(__p); } 280 281 template<typename _Tp> 282 static typename enable_if<!__destroy_helper<_Tp>::value, void>::type 283 _S_destroy(_Alloc&, _Tp* __p) 284 { __p->~_Tp(); } 285 286 template<typename _Alloc2> 287 struct __maxsize_helper 288 { 289 template<typename _Alloc3, 290 typename = decltype(std::declval<_Alloc3*>()->max_size())> 291 static true_type __test(int); 292 293 template<typename> 294 static false_type __test(...); 295 296 typedef decltype(__test<_Alloc2>(0)) type; 297 static const bool value = type::value; 298 }; 299 300 template<typename _Alloc2> 301 static typename 302 enable_if<__maxsize_helper<_Alloc2>::value, size_type>::type 303 _S_max_size(_Alloc2& __a) 304 { return __a.max_size(); } 305 306 template<typename _Alloc2> 307 static typename 308 enable_if<!__maxsize_helper<_Alloc2>::value, size_type>::type 309 _S_max_size(_Alloc2&) 310 { return __gnu_cxx::__numeric_traits<size_type>::__max; } 311 312 template<typename _Alloc2> 313 struct __select_helper 314 { 315 template<typename _Alloc3, typename 316 = decltype(std::declval<_Alloc3*>() 317 ->select_on_container_copy_construction())> 318 static true_type __test(int); 319 320 template<typename> 321 static false_type __test(...); 322 323 typedef decltype(__test<_Alloc2>(0)) type; 324 static const bool value = type::value; 325 }; 326 template<typename _Alloc2> 327 static typename 328 enable_if<__select_helper<_Alloc2>::value, _Alloc2>::type 329 _S_select(_Alloc2& __a) 330 { return __a.select_on_container_copy_construction(); } 331 332 template<typename _Alloc2> 333 static typename 334 enable_if<!__select_helper<_Alloc2>::value, _Alloc2>::type 335 _S_select(_Alloc2& __a) 336 { return __a; } 337 338 public: 339 340 /** 341 * @brief Allocate memory. 342 * @param __a An allocator. 343 * @param __n The number of objects to allocate space for. 344 * 345 * Calls @c a.allocate(n) 346 */ 347 static pointer 348 allocate(_Alloc& __a, size_type __n) 349 { return __a.allocate(__n); } 350 351 /** 352 * @brief Allocate memory. 353 * @param __a An allocator. 354 * @param __n The number of objects to allocate space for. 355 * @param __hint Aid to locality. 356 * @return Memory of suitable size and alignment for @a n objects 357 * of type @c value_type 358 * 359 * Returns <tt> a.allocate(n, hint) </tt> if that expression is 360 * well-formed, otherwise returns @c a.allocate(n) 361 */ 362 static pointer 363 allocate(_Alloc& __a, size_type __n, const_void_pointer __hint) 364 { return _S_allocate(__a, __n, __hint); } 365 366 /** 367 * @brief Deallocate memory. 368 * @param __a An allocator. 369 * @param __p Pointer to the memory to deallocate. 370 * @param __n The number of objects space was allocated for. 371 * 372 * Calls <tt> a.deallocate(p, n) </tt> 373 */ 374 static void deallocate(_Alloc& __a, pointer __p, size_type __n) 375 { __a.deallocate(__p, __n); } 376 377 /** 378 * @brief Construct an object of type @a _Tp 379 * @param __a An allocator. 380 * @param __p Pointer to memory of suitable size and alignment for Tp 381 * @param __args Constructor arguments. 382 * 383 * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt> 384 * if that expression is well-formed, otherwise uses placement-new 385 * to construct an object of type @a _Tp at location @a __p from the 386 * arguments @a __args... 387 */ 388 template<typename _Tp, typename... _Args> 389 static void construct(_Alloc& __a, _Tp* __p, _Args&&... __args) 390 { _S_construct(__a, __p, std::forward<_Args>(__args)...); } 391 392 /** 393 * @brief Destroy an object of type @a _Tp 394 * @param __a An allocator. 395 * @param __p Pointer to the object to destroy 396 * 397 * Calls @c __a.destroy(__p) if that expression is well-formed, 398 * otherwise calls @c __p->~_Tp() 399 */ 400 template <class _Tp> 401 static void destroy(_Alloc& __a, _Tp* __p) 402 { _S_destroy(__a, __p); } 403 404 /** 405 * @brief The maximum supported allocation size 406 * @param __a An allocator. 407 * @return @c __a.max_size() or @c numeric_limits<size_type>::max() 408 * 409 * Returns @c __a.max_size() if that expression is well-formed, 410 * otherwise returns @c numeric_limits<size_type>::max() 411 */ 412 static size_type max_size(const _Alloc& __a) 413 { return _S_max_size(__a); } 414 415 /** 416 * @brief Obtain an allocator to use when copying a container. 417 * @param __rhs An allocator. 418 * @return @c __rhs.select_on_container_copy_construction() or @a __rhs 419 * 420 * Returns @c __rhs.select_on_container_copy_construction() if that 421 * expression is well-formed, otherwise returns @a __rhs 422 */ 423 static _Alloc 424 select_on_container_copy_construction(const _Alloc& __rhs) 425 { return _S_select(__rhs); } 426 }; 427 428 template<typename _Alloc> 429 template<typename _Alloc2> 430 const bool allocator_traits<_Alloc>::__allocate_helper<_Alloc2>::value; 431 432 template<typename _Alloc> 433 template<typename _Tp, typename... _Args> 434 const bool 435 allocator_traits<_Alloc>::__construct_helper<_Tp, _Args...>::value; 436 437 template<typename _Alloc> 438 template<typename _Tp> 439 const bool allocator_traits<_Alloc>::__destroy_helper<_Tp>::value; 440 441 template<typename _Alloc> 442 template<typename _Alloc2> 443 const bool allocator_traits<_Alloc>::__maxsize_helper<_Alloc2>::value; 444 445 template<typename _Alloc> 446 template<typename _Alloc2> 447 const bool allocator_traits<_Alloc>::__select_helper<_Alloc2>::value; 448 449 template<typename _Alloc> 450 inline void 451 __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) 452 { __one = __two; } 453 454 template<typename _Alloc> 455 inline void 456 __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type) 457 { } 458 459 template<typename _Alloc> 460 inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two) 461 { 462 typedef allocator_traits<_Alloc> __traits; 463 typedef typename __traits::propagate_on_container_copy_assignment __pocca; 464 __do_alloc_on_copy(__one, __two, __pocca()); 465 } 466 467 template<typename _Alloc> 468 inline _Alloc __alloc_on_copy(const _Alloc& __a) 469 { 470 typedef allocator_traits<_Alloc> __traits; 471 return __traits::select_on_container_copy_construction(__a); 472 } 473 474 template<typename _Alloc> 475 inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type) 476 { __one = std::move(__two); } 477 478 template<typename _Alloc> 479 inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type) 480 { } 481 482 template<typename _Alloc> 483 inline void __alloc_on_move(_Alloc& __one, _Alloc& __two) 484 { 485 typedef allocator_traits<_Alloc> __traits; 486 typedef typename __traits::propagate_on_container_move_assignment __pocma; 487 __do_alloc_on_move(__one, __two, __pocma()); 488 } 489 490 template<typename _Alloc> 491 inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type) 492 { 493 using std::swap; 494 swap(__one, __two); 495 } 496 497 template<typename _Alloc> 498 inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type) 499 { } 500 501 template<typename _Alloc> 502 inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two) 503 { 504 typedef allocator_traits<_Alloc> __traits; 505 typedef typename __traits::propagate_on_container_swap __pocs; 506 __do_alloc_on_swap(__one, __two, __pocs()); 507 } 508 509 _GLIBCXX_END_NAMESPACE_VERSION 510 } // namespace std 511 512 #endif 513 #endif 514