1// -*- C++ -*- 2//===-------------------------- scoped_allocator --------------------------===// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is dual licensed under the MIT and the University of Illinois Open 7// Source Licenses. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10 11#ifndef _LIBCPP_SCOPED_ALLOCATOR 12#define _LIBCPP_SCOPED_ALLOCATOR 13 14/* 15 scoped_allocator synopsis 16 17namespace std 18{ 19 20template <class OuterAlloc, class... InnerAllocs> 21class scoped_allocator_adaptor : public OuterAlloc 22{ 23 typedef allocator_traits<OuterAlloc> OuterTraits; // exposition only 24 scoped_allocator_adaptor<InnerAllocs...> inner; // exposition only 25public: 26 27 typedef OuterAlloc outer_allocator_type; 28 typedef see below inner_allocator_type; 29 30 typedef typename OuterTraits::value_type value_type; 31 typedef typename OuterTraits::size_type size_type; 32 typedef typename OuterTraits::difference_type difference_type; 33 typedef typename OuterTraits::pointer pointer; 34 typedef typename OuterTraits::const_pointer const_pointer; 35 typedef typename OuterTraits::void_pointer void_pointer; 36 typedef typename OuterTraits::const_void_pointer const_void_pointer; 37 38 typedef see below propagate_on_container_copy_assignment; 39 typedef see below propagate_on_container_move_assignment; 40 typedef see below propagate_on_container_swap; 41 typedef see below is_always_equal; 42 43 template <class Tp> 44 struct rebind 45 { 46 typedef scoped_allocator_adaptor< 47 OuterTraits::template rebind_alloc<Tp>, InnerAllocs...> other; 48 }; 49 50 scoped_allocator_adaptor(); 51 template <class OuterA2> 52 scoped_allocator_adaptor(OuterA2&& outerAlloc, 53 const InnerAllocs&... innerAllocs) noexcept; 54 scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; 55 scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; 56 template <class OuterA2> 57 scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept; 58 template <class OuterA2> 59 scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept; 60 61 ~scoped_allocator_adaptor(); 62 63 inner_allocator_type& inner_allocator() noexcept; 64 const inner_allocator_type& inner_allocator() const noexcept; 65 66 outer_allocator_type& outer_allocator() noexcept; 67 const outer_allocator_type& outer_allocator() const noexcept; 68 69 pointer allocate(size_type n); 70 pointer allocate(size_type n, const_void_pointer hint); 71 void deallocate(pointer p, size_type n) noexcept; 72 73 size_type max_size() const; 74 template <class T, class... Args> void construct(T* p, Args&& args); 75 template <class T1, class T2, class... Args1, class... Args2> 76 void construct(pair<T1, T2>* p, piecewise_construct t, tuple<Args1...> x, 77 tuple<Args2...> y); 78 template <class T1, class T2> 79 void construct(pair<T1, T2>* p); 80 template <class T1, class T2, class U, class V> 81 void construct(pair<T1, T2>* p, U&& x, V&& y); 82 template <class T1, class T2, class U, class V> 83 void construct(pair<T1, T2>* p, const pair<U, V>& x); 84 template <class T1, class T2, class U, class V> 85 void construct(pair<T1, T2>* p, pair<U, V>&& x); 86 template <class T> void destroy(T* p); 87 88 template <class T> void destroy(T* p) noexcept; 89 90 scoped_allocator_adaptor select_on_container_copy_construction() const noexcept; 91}; 92 93template <class OuterA1, class OuterA2, class... InnerAllocs> 94 bool 95 operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, 96 const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept; 97 98template <class OuterA1, class OuterA2, class... InnerAllocs> 99 bool 100 operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, 101 const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept; 102 103} // std 104 105*/ 106 107#include <__config> 108#include <memory> 109 110#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 111#pragma GCC system_header 112#endif 113 114_LIBCPP_BEGIN_NAMESPACE_STD 115 116#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_ADVANCED_SFINAE) 117 118// scoped_allocator_adaptor 119 120template <class ..._Allocs> 121class scoped_allocator_adaptor; 122 123template <class ..._Allocs> struct __get_poc_copy_assignment; 124 125template <class _A0> 126struct __get_poc_copy_assignment<_A0> 127{ 128 static const bool value = allocator_traits<_A0>:: 129 propagate_on_container_copy_assignment::value; 130}; 131 132template <class _A0, class ..._Allocs> 133struct __get_poc_copy_assignment<_A0, _Allocs...> 134{ 135 static const bool value = 136 allocator_traits<_A0>::propagate_on_container_copy_assignment::value || 137 __get_poc_copy_assignment<_Allocs...>::value; 138}; 139 140template <class ..._Allocs> struct __get_poc_move_assignment; 141 142template <class _A0> 143struct __get_poc_move_assignment<_A0> 144{ 145 static const bool value = allocator_traits<_A0>:: 146 propagate_on_container_move_assignment::value; 147}; 148 149template <class _A0, class ..._Allocs> 150struct __get_poc_move_assignment<_A0, _Allocs...> 151{ 152 static const bool value = 153 allocator_traits<_A0>::propagate_on_container_move_assignment::value || 154 __get_poc_move_assignment<_Allocs...>::value; 155}; 156 157template <class ..._Allocs> struct __get_poc_swap; 158 159template <class _A0> 160struct __get_poc_swap<_A0> 161{ 162 static const bool value = allocator_traits<_A0>:: 163 propagate_on_container_swap::value; 164}; 165 166template <class _A0, class ..._Allocs> 167struct __get_poc_swap<_A0, _Allocs...> 168{ 169 static const bool value = 170 allocator_traits<_A0>::propagate_on_container_swap::value || 171 __get_poc_swap<_Allocs...>::value; 172}; 173 174template <class ..._Allocs> struct __get_is_always_equal; 175 176template <class _A0> 177struct __get_is_always_equal<_A0> 178{ 179 static const bool value = allocator_traits<_A0>::is_always_equal::value; 180}; 181 182template <class _A0, class ..._Allocs> 183struct __get_is_always_equal<_A0, _Allocs...> 184{ 185 static const bool value = 186 allocator_traits<_A0>::is_always_equal::value && 187 __get_is_always_equal<_Allocs...>::value; 188}; 189 190template <class ..._Allocs> 191class __scoped_allocator_storage; 192 193template <class _OuterAlloc, class... _InnerAllocs> 194class __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> 195 : public _OuterAlloc 196{ 197 typedef _OuterAlloc outer_allocator_type; 198protected: 199 typedef scoped_allocator_adaptor<_InnerAllocs...> inner_allocator_type; 200 201private: 202 inner_allocator_type __inner_; 203 204protected: 205 206 _LIBCPP_INLINE_VISIBILITY 207 __scoped_allocator_storage() _NOEXCEPT {} 208 209 template <class _OuterA2, 210 class = typename enable_if< 211 is_constructible<outer_allocator_type, _OuterA2>::value 212 >::type> 213 _LIBCPP_INLINE_VISIBILITY 214 __scoped_allocator_storage(_OuterA2&& __outerAlloc, 215 const _InnerAllocs& ...__innerAllocs) _NOEXCEPT 216 : outer_allocator_type(_VSTD::forward<_OuterA2>(__outerAlloc)), 217 __inner_(__innerAllocs...) {} 218 219 template <class _OuterA2, 220 class = typename enable_if< 221 is_constructible<outer_allocator_type, const _OuterA2&>::value 222 >::type> 223 _LIBCPP_INLINE_VISIBILITY 224 __scoped_allocator_storage( 225 const __scoped_allocator_storage<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT 226 : outer_allocator_type(__other.outer_allocator()), 227 __inner_(__other.inner_allocator()) {} 228 229 template <class _OuterA2, 230 class = typename enable_if< 231 is_constructible<outer_allocator_type, _OuterA2>::value 232 >::type> 233 _LIBCPP_INLINE_VISIBILITY 234 __scoped_allocator_storage( 235 __scoped_allocator_storage<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT 236 : outer_allocator_type(_VSTD::move(__other.outer_allocator())), 237 __inner_(_VSTD::move(__other.inner_allocator())) {} 238 239 template <class _OuterA2, 240 class = typename enable_if< 241 is_constructible<outer_allocator_type, _OuterA2>::value 242 >::type> 243 _LIBCPP_INLINE_VISIBILITY 244 __scoped_allocator_storage(_OuterA2&& __o, 245 const inner_allocator_type& __i) _NOEXCEPT 246 : outer_allocator_type(_VSTD::forward<_OuterA2>(__o)), 247 __inner_(__i) 248 { 249 } 250 251 _LIBCPP_INLINE_VISIBILITY 252 inner_allocator_type& inner_allocator() _NOEXCEPT {return __inner_;} 253 _LIBCPP_INLINE_VISIBILITY 254 const inner_allocator_type& inner_allocator() const _NOEXCEPT {return __inner_;} 255 256 _LIBCPP_INLINE_VISIBILITY 257 outer_allocator_type& outer_allocator() _NOEXCEPT 258 {return static_cast<outer_allocator_type&>(*this);} 259 _LIBCPP_INLINE_VISIBILITY 260 const outer_allocator_type& outer_allocator() const _NOEXCEPT 261 {return static_cast<const outer_allocator_type&>(*this);} 262 263 scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...> 264 _LIBCPP_INLINE_VISIBILITY 265 select_on_container_copy_construction() const _NOEXCEPT 266 { 267 return scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...> 268 ( 269 allocator_traits<outer_allocator_type>:: 270 select_on_container_copy_construction(outer_allocator()), 271 allocator_traits<inner_allocator_type>:: 272 select_on_container_copy_construction(inner_allocator()) 273 ); 274 } 275 276 template <class...> friend class __scoped_allocator_storage; 277}; 278 279template <class _OuterAlloc> 280class __scoped_allocator_storage<_OuterAlloc> 281 : public _OuterAlloc 282{ 283 typedef _OuterAlloc outer_allocator_type; 284protected: 285 typedef scoped_allocator_adaptor<_OuterAlloc> inner_allocator_type; 286 287 _LIBCPP_INLINE_VISIBILITY 288 __scoped_allocator_storage() _NOEXCEPT {} 289 290 template <class _OuterA2, 291 class = typename enable_if< 292 is_constructible<outer_allocator_type, _OuterA2>::value 293 >::type> 294 _LIBCPP_INLINE_VISIBILITY 295 __scoped_allocator_storage(_OuterA2&& __outerAlloc) _NOEXCEPT 296 : outer_allocator_type(_VSTD::forward<_OuterA2>(__outerAlloc)) {} 297 298 template <class _OuterA2, 299 class = typename enable_if< 300 is_constructible<outer_allocator_type, const _OuterA2&>::value 301 >::type> 302 _LIBCPP_INLINE_VISIBILITY 303 __scoped_allocator_storage( 304 const __scoped_allocator_storage<_OuterA2>& __other) _NOEXCEPT 305 : outer_allocator_type(__other.outer_allocator()) {} 306 307 template <class _OuterA2, 308 class = typename enable_if< 309 is_constructible<outer_allocator_type, _OuterA2>::value 310 >::type> 311 _LIBCPP_INLINE_VISIBILITY 312 __scoped_allocator_storage( 313 __scoped_allocator_storage<_OuterA2>&& __other) _NOEXCEPT 314 : outer_allocator_type(_VSTD::move(__other.outer_allocator())) {} 315 316 _LIBCPP_INLINE_VISIBILITY 317 inner_allocator_type& inner_allocator() _NOEXCEPT 318 {return static_cast<inner_allocator_type&>(*this);} 319 _LIBCPP_INLINE_VISIBILITY 320 const inner_allocator_type& inner_allocator() const _NOEXCEPT 321 {return static_cast<const inner_allocator_type&>(*this);} 322 323 _LIBCPP_INLINE_VISIBILITY 324 outer_allocator_type& outer_allocator() _NOEXCEPT 325 {return static_cast<outer_allocator_type&>(*this);} 326 _LIBCPP_INLINE_VISIBILITY 327 const outer_allocator_type& outer_allocator() const _NOEXCEPT 328 {return static_cast<const outer_allocator_type&>(*this);} 329 330 _LIBCPP_INLINE_VISIBILITY 331 scoped_allocator_adaptor<outer_allocator_type> 332 select_on_container_copy_construction() const _NOEXCEPT 333 {return scoped_allocator_adaptor<outer_allocator_type>( 334 allocator_traits<outer_allocator_type>:: 335 select_on_container_copy_construction(outer_allocator()) 336 );} 337 338 __scoped_allocator_storage(const outer_allocator_type& __o, 339 const inner_allocator_type& __i) _NOEXCEPT; 340 341 template <class...> friend class __scoped_allocator_storage; 342}; 343 344// __outermost 345 346template <class _Alloc> 347decltype(declval<_Alloc>().outer_allocator(), true_type()) 348__has_outer_allocator_test(_Alloc&& __a); 349 350template <class _Alloc> 351false_type 352__has_outer_allocator_test(const volatile _Alloc& __a); 353 354template <class _Alloc> 355struct __has_outer_allocator 356 : public common_type 357 < 358 decltype(__has_outer_allocator_test(declval<_Alloc&>())) 359 >::type 360{ 361}; 362 363template <class _Alloc, bool = __has_outer_allocator<_Alloc>::value> 364struct __outermost 365{ 366 typedef _Alloc type; 367 _LIBCPP_INLINE_VISIBILITY 368 type& operator()(type& __a) const _NOEXCEPT {return __a;} 369}; 370 371template <class _Alloc> 372struct __outermost<_Alloc, true> 373{ 374 typedef typename remove_reference 375 < 376 decltype(_VSTD::declval<_Alloc>().outer_allocator()) 377 >::type _OuterAlloc; 378 typedef typename __outermost<_OuterAlloc>::type type; 379 _LIBCPP_INLINE_VISIBILITY 380 type& operator()(_Alloc& __a) const _NOEXCEPT 381 {return __outermost<_OuterAlloc>()(__a.outer_allocator());} 382}; 383 384template <class _OuterAlloc, class... _InnerAllocs> 385class _LIBCPP_TYPE_VIS_ONLY scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...> 386 : public __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> 387{ 388 typedef __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> base; 389 typedef allocator_traits<_OuterAlloc> _OuterTraits; 390public: 391 typedef _OuterAlloc outer_allocator_type; 392 typedef typename base::inner_allocator_type inner_allocator_type; 393 typedef typename _OuterTraits::size_type size_type; 394 typedef typename _OuterTraits::difference_type difference_type; 395 typedef typename _OuterTraits::pointer pointer; 396 typedef typename _OuterTraits::const_pointer const_pointer; 397 typedef typename _OuterTraits::void_pointer void_pointer; 398 typedef typename _OuterTraits::const_void_pointer const_void_pointer; 399 400 typedef integral_constant 401 < 402 bool, 403 __get_poc_copy_assignment<outer_allocator_type, 404 _InnerAllocs...>::value 405 > propagate_on_container_copy_assignment; 406 typedef integral_constant 407 < 408 bool, 409 __get_poc_move_assignment<outer_allocator_type, 410 _InnerAllocs...>::value 411 > propagate_on_container_move_assignment; 412 typedef integral_constant 413 < 414 bool, 415 __get_poc_swap<outer_allocator_type, _InnerAllocs...>::value 416 > propagate_on_container_swap; 417 typedef integral_constant 418 < 419 bool, 420 __get_is_always_equal<outer_allocator_type, _InnerAllocs...>::value 421 > is_always_equal; 422 423 template <class _Tp> 424 struct rebind 425 { 426 typedef scoped_allocator_adaptor 427 < 428 typename _OuterTraits::template rebind_alloc<_Tp>, _InnerAllocs... 429 > other; 430 }; 431 432 _LIBCPP_INLINE_VISIBILITY 433 scoped_allocator_adaptor() _NOEXCEPT {} 434 template <class _OuterA2, 435 class = typename enable_if< 436 is_constructible<outer_allocator_type, _OuterA2>::value 437 >::type> 438 _LIBCPP_INLINE_VISIBILITY 439 scoped_allocator_adaptor(_OuterA2&& __outerAlloc, 440 const _InnerAllocs& ...__innerAllocs) _NOEXCEPT 441 : base(_VSTD::forward<_OuterA2>(__outerAlloc), __innerAllocs...) {} 442 // scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) = default; 443 template <class _OuterA2, 444 class = typename enable_if< 445 is_constructible<outer_allocator_type, const _OuterA2&>::value 446 >::type> 447 _LIBCPP_INLINE_VISIBILITY 448 scoped_allocator_adaptor( 449 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT 450 : base(__other) {} 451 template <class _OuterA2, 452 class = typename enable_if< 453 is_constructible<outer_allocator_type, _OuterA2>::value 454 >::type> 455 _LIBCPP_INLINE_VISIBILITY 456 scoped_allocator_adaptor( 457 scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT 458 : base(_VSTD::move(__other)) {} 459 460 // ~scoped_allocator_adaptor() = default; 461 462 _LIBCPP_INLINE_VISIBILITY 463 inner_allocator_type& inner_allocator() _NOEXCEPT 464 {return base::inner_allocator();} 465 _LIBCPP_INLINE_VISIBILITY 466 const inner_allocator_type& inner_allocator() const _NOEXCEPT 467 {return base::inner_allocator();} 468 469 _LIBCPP_INLINE_VISIBILITY 470 outer_allocator_type& outer_allocator() _NOEXCEPT 471 {return base::outer_allocator();} 472 _LIBCPP_INLINE_VISIBILITY 473 const outer_allocator_type& outer_allocator() const _NOEXCEPT 474 {return base::outer_allocator();} 475 476 _LIBCPP_INLINE_VISIBILITY 477 pointer allocate(size_type __n) 478 {return allocator_traits<outer_allocator_type>:: 479 allocate(outer_allocator(), __n);} 480 _LIBCPP_INLINE_VISIBILITY 481 pointer allocate(size_type __n, const_void_pointer __hint) 482 {return allocator_traits<outer_allocator_type>:: 483 allocate(outer_allocator(), __n, __hint);} 484 485 _LIBCPP_INLINE_VISIBILITY 486 void deallocate(pointer __p, size_type __n) _NOEXCEPT 487 {allocator_traits<outer_allocator_type>:: 488 deallocate(outer_allocator(), __p, __n);} 489 490 _LIBCPP_INLINE_VISIBILITY 491 size_type max_size() const 492 {return allocator_traits<outer_allocator_type>::max_size(outer_allocator());} 493 494 template <class _Tp, class... _Args> 495 _LIBCPP_INLINE_VISIBILITY 496 void construct(_Tp* __p, _Args&& ...__args) 497 {__construct(__uses_alloc_ctor<_Tp, inner_allocator_type, _Args...>(), 498 __p, _VSTD::forward<_Args>(__args)...);} 499 template <class _Tp> 500 _LIBCPP_INLINE_VISIBILITY 501 void destroy(_Tp* __p) 502 { 503 typedef __outermost<outer_allocator_type> _OM; 504 allocator_traits<typename _OM::type>:: 505 destroy(_OM()(outer_allocator()), __p); 506 } 507 508 _LIBCPP_INLINE_VISIBILITY 509 scoped_allocator_adaptor select_on_container_copy_construction() const _NOEXCEPT 510 {return base::select_on_container_copy_construction();} 511 512private: 513 514 template <class _OuterA2, 515 class = typename enable_if< 516 is_constructible<outer_allocator_type, _OuterA2>::value 517 >::type> 518 _LIBCPP_INLINE_VISIBILITY 519 scoped_allocator_adaptor(_OuterA2&& __o, 520 const inner_allocator_type& __i) _NOEXCEPT 521 : base(_VSTD::forward<_OuterA2>(__o), __i) {} 522 523 template <class _Tp, class... _Args> 524 _LIBCPP_INLINE_VISIBILITY 525 void __construct(integral_constant<int, 0>, _Tp* __p, _Args&& ...__args) 526 { 527 typedef __outermost<outer_allocator_type> _OM; 528 allocator_traits<typename _OM::type>::construct 529 ( 530 _OM()(outer_allocator()), 531 __p, 532 _VSTD::forward<_Args>(__args)... 533 ); 534 } 535 536 template <class _Tp, class... _Args> 537 _LIBCPP_INLINE_VISIBILITY 538 void __construct(integral_constant<int, 1>, _Tp* __p, _Args&& ...__args) 539 { 540 typedef __outermost<outer_allocator_type> _OM; 541 allocator_traits<typename _OM::type>::construct 542 ( 543 _OM()(outer_allocator()), 544 __p, 545 allocator_arg, 546 inner_allocator(), 547 _VSTD::forward<_Args>(__args)... 548 ); 549 } 550 551 template <class _Tp, class... _Args> 552 _LIBCPP_INLINE_VISIBILITY 553 void __construct(integral_constant<int, 2>, _Tp* __p, _Args&& ...__args) 554 { 555 typedef __outermost<outer_allocator_type> _OM; 556 allocator_traits<typename _OM::type>::construct 557 ( 558 _OM()(outer_allocator()), 559 __p, 560 _VSTD::forward<_Args>(__args)..., 561 inner_allocator() 562 ); 563 } 564 565 template <class...> friend class __scoped_allocator_storage; 566}; 567 568template <class _OuterA1, class _OuterA2> 569inline _LIBCPP_INLINE_VISIBILITY 570bool 571operator==(const scoped_allocator_adaptor<_OuterA1>& __a, 572 const scoped_allocator_adaptor<_OuterA2>& __b) _NOEXCEPT 573{ 574 return __a.outer_allocator() == __b.outer_allocator(); 575} 576 577template <class _OuterA1, class _OuterA2, class _InnerA0, class... _InnerAllocs> 578inline _LIBCPP_INLINE_VISIBILITY 579bool 580operator==(const scoped_allocator_adaptor<_OuterA1, _InnerA0, _InnerAllocs...>& __a, 581 const scoped_allocator_adaptor<_OuterA2, _InnerA0, _InnerAllocs...>& __b) _NOEXCEPT 582{ 583 return __a.outer_allocator() == __b.outer_allocator() && 584 __a.inner_allocator() == __b.inner_allocator(); 585} 586 587template <class _OuterA1, class _OuterA2, class... _InnerAllocs> 588inline _LIBCPP_INLINE_VISIBILITY 589bool 590operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a, 591 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __b) _NOEXCEPT 592{ 593 return !(__a == __b); 594} 595 596#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_ADVANCED_SFINAE) 597 598_LIBCPP_END_NAMESPACE_STD 599 600#endif // _LIBCPP_SCOPED_ALLOCATOR 601