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 _A0, class ..._Allocs> 175struct __get_poc_always_equal<_A0, _Allocs...> 176{ 177 static const bool value = 178 allocator_traits<_A0>::is_always_equal::value || 179 __get_poc_always_equal<_Allocs...>::value; 180}; 181 182template <class ..._Allocs> 183class __scoped_allocator_storage; 184 185template <class _OuterAlloc, class... _InnerAllocs> 186class __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> 187 : public _OuterAlloc 188{ 189 typedef _OuterAlloc outer_allocator_type; 190protected: 191 typedef scoped_allocator_adaptor<_InnerAllocs...> inner_allocator_type; 192 193private: 194 inner_allocator_type __inner_; 195 196protected: 197 198 _LIBCPP_INLINE_VISIBILITY 199 __scoped_allocator_storage() _NOEXCEPT {} 200 201 template <class _OuterA2, 202 class = typename enable_if< 203 is_constructible<outer_allocator_type, _OuterA2>::value 204 >::type> 205 _LIBCPP_INLINE_VISIBILITY 206 __scoped_allocator_storage(_OuterA2&& __outerAlloc, 207 const _InnerAllocs& ...__innerAllocs) _NOEXCEPT 208 : outer_allocator_type(_VSTD::forward<_OuterA2>(__outerAlloc)), 209 __inner_(__innerAllocs...) {} 210 211 template <class _OuterA2, 212 class = typename enable_if< 213 is_constructible<outer_allocator_type, const _OuterA2&>::value 214 >::type> 215 _LIBCPP_INLINE_VISIBILITY 216 __scoped_allocator_storage( 217 const __scoped_allocator_storage<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT 218 : outer_allocator_type(__other.outer_allocator()), 219 __inner_(__other.inner_allocator()) {} 220 221 template <class _OuterA2, 222 class = typename enable_if< 223 is_constructible<outer_allocator_type, _OuterA2>::value 224 >::type> 225 _LIBCPP_INLINE_VISIBILITY 226 __scoped_allocator_storage( 227 __scoped_allocator_storage<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT 228 : outer_allocator_type(_VSTD::move(__other.outer_allocator())), 229 __inner_(_VSTD::move(__other.inner_allocator())) {} 230 231 template <class _OuterA2, 232 class = typename enable_if< 233 is_constructible<outer_allocator_type, _OuterA2>::value 234 >::type> 235 _LIBCPP_INLINE_VISIBILITY 236 __scoped_allocator_storage(_OuterA2&& __o, 237 const inner_allocator_type& __i) _NOEXCEPT 238 : outer_allocator_type(_VSTD::forward<_OuterA2>(__o)), 239 __inner_(__i) 240 { 241 } 242 243 _LIBCPP_INLINE_VISIBILITY 244 inner_allocator_type& inner_allocator() _NOEXCEPT {return __inner_;} 245 _LIBCPP_INLINE_VISIBILITY 246 const inner_allocator_type& inner_allocator() const _NOEXCEPT {return __inner_;} 247 248 _LIBCPP_INLINE_VISIBILITY 249 outer_allocator_type& outer_allocator() _NOEXCEPT 250 {return static_cast<outer_allocator_type&>(*this);} 251 _LIBCPP_INLINE_VISIBILITY 252 const outer_allocator_type& outer_allocator() const _NOEXCEPT 253 {return static_cast<const outer_allocator_type&>(*this);} 254 255 scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...> 256 _LIBCPP_INLINE_VISIBILITY 257 select_on_container_copy_construction() const _NOEXCEPT 258 { 259 return scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...> 260 ( 261 allocator_traits<outer_allocator_type>:: 262 select_on_container_copy_construction(outer_allocator()), 263 allocator_traits<inner_allocator_type>:: 264 select_on_container_copy_construction(inner_allocator()) 265 ); 266 } 267 268 template <class...> friend class __scoped_allocator_storage; 269}; 270 271template <class _OuterAlloc> 272class __scoped_allocator_storage<_OuterAlloc> 273 : public _OuterAlloc 274{ 275 typedef _OuterAlloc outer_allocator_type; 276protected: 277 typedef scoped_allocator_adaptor<_OuterAlloc> inner_allocator_type; 278 279 _LIBCPP_INLINE_VISIBILITY 280 __scoped_allocator_storage() _NOEXCEPT {} 281 282 template <class _OuterA2, 283 class = typename enable_if< 284 is_constructible<outer_allocator_type, _OuterA2>::value 285 >::type> 286 _LIBCPP_INLINE_VISIBILITY 287 __scoped_allocator_storage(_OuterA2&& __outerAlloc) _NOEXCEPT 288 : outer_allocator_type(_VSTD::forward<_OuterA2>(__outerAlloc)) {} 289 290 template <class _OuterA2, 291 class = typename enable_if< 292 is_constructible<outer_allocator_type, const _OuterA2&>::value 293 >::type> 294 _LIBCPP_INLINE_VISIBILITY 295 __scoped_allocator_storage( 296 const __scoped_allocator_storage<_OuterA2>& __other) _NOEXCEPT 297 : outer_allocator_type(__other.outer_allocator()) {} 298 299 template <class _OuterA2, 300 class = typename enable_if< 301 is_constructible<outer_allocator_type, _OuterA2>::value 302 >::type> 303 _LIBCPP_INLINE_VISIBILITY 304 __scoped_allocator_storage( 305 __scoped_allocator_storage<_OuterA2>&& __other) _NOEXCEPT 306 : outer_allocator_type(_VSTD::move(__other.outer_allocator())) {} 307 308 _LIBCPP_INLINE_VISIBILITY 309 inner_allocator_type& inner_allocator() _NOEXCEPT 310 {return static_cast<inner_allocator_type&>(*this);} 311 _LIBCPP_INLINE_VISIBILITY 312 const inner_allocator_type& inner_allocator() const _NOEXCEPT 313 {return static_cast<const inner_allocator_type&>(*this);} 314 315 _LIBCPP_INLINE_VISIBILITY 316 outer_allocator_type& outer_allocator() _NOEXCEPT 317 {return static_cast<outer_allocator_type&>(*this);} 318 _LIBCPP_INLINE_VISIBILITY 319 const outer_allocator_type& outer_allocator() const _NOEXCEPT 320 {return static_cast<const outer_allocator_type&>(*this);} 321 322 _LIBCPP_INLINE_VISIBILITY 323 scoped_allocator_adaptor<outer_allocator_type> 324 select_on_container_copy_construction() const _NOEXCEPT 325 {return scoped_allocator_adaptor<outer_allocator_type>( 326 allocator_traits<outer_allocator_type>:: 327 select_on_container_copy_construction(outer_allocator()) 328 );} 329 330 __scoped_allocator_storage(const outer_allocator_type& __o, 331 const inner_allocator_type& __i) _NOEXCEPT; 332 333 template <class...> friend class __scoped_allocator_storage; 334}; 335 336// __outermost 337 338template <class _Alloc> 339decltype(declval<_Alloc>().outer_allocator(), true_type()) 340__has_outer_allocator_test(_Alloc&& __a); 341 342template <class _Alloc> 343false_type 344__has_outer_allocator_test(const volatile _Alloc& __a); 345 346template <class _Alloc> 347struct __has_outer_allocator 348 : public common_type 349 < 350 decltype(__has_outer_allocator_test(declval<_Alloc&>())) 351 >::type 352{ 353}; 354 355template <class _Alloc, bool = __has_outer_allocator<_Alloc>::value> 356struct __outermost 357{ 358 typedef _Alloc type; 359 _LIBCPP_INLINE_VISIBILITY 360 type& operator()(type& __a) const _NOEXCEPT {return __a;} 361}; 362 363template <class _Alloc> 364struct __outermost<_Alloc, true> 365{ 366 typedef typename remove_reference 367 < 368 decltype(_VSTD::declval<_Alloc>().outer_allocator()) 369 >::type _OuterAlloc; 370 typedef typename __outermost<_OuterAlloc>::type type; 371 _LIBCPP_INLINE_VISIBILITY 372 type& operator()(_Alloc& __a) const _NOEXCEPT 373 {return __outermost<_OuterAlloc>()(__a.outer_allocator());} 374}; 375 376template <class _OuterAlloc, class... _InnerAllocs> 377class _LIBCPP_TYPE_VIS_ONLY scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...> 378 : public __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> 379{ 380 typedef __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> base; 381 typedef allocator_traits<_OuterAlloc> _OuterTraits; 382public: 383 typedef _OuterAlloc outer_allocator_type; 384 typedef typename base::inner_allocator_type inner_allocator_type; 385 typedef typename _OuterTraits::size_type size_type; 386 typedef typename _OuterTraits::difference_type difference_type; 387 typedef typename _OuterTraits::pointer pointer; 388 typedef typename _OuterTraits::const_pointer const_pointer; 389 typedef typename _OuterTraits::void_pointer void_pointer; 390 typedef typename _OuterTraits::const_void_pointer const_void_pointer; 391 392 typedef integral_constant 393 < 394 bool, 395 __get_poc_copy_assignment<outer_allocator_type, 396 _InnerAllocs...>::value 397 > propagate_on_container_copy_assignment; 398 typedef integral_constant 399 < 400 bool, 401 __get_poc_move_assignment<outer_allocator_type, 402 _InnerAllocs...>::value 403 > propagate_on_container_move_assignment; 404 typedef integral_constant 405 < 406 bool, 407 __get_poc_swap<outer_allocator_type, _InnerAllocs...>::value 408 > propagate_on_container_swap; 409 typedef integral_constant 410 < 411 bool, 412 __get_poc_always_equal<outer_allocator_type, _InnerAllocs...>::value 413 > is_always_equal; 414 415 template <class _Tp> 416 struct rebind 417 { 418 typedef scoped_allocator_adaptor 419 < 420 typename _OuterTraits::template rebind_alloc<_Tp>, _InnerAllocs... 421 > other; 422 }; 423 424 _LIBCPP_INLINE_VISIBILITY 425 scoped_allocator_adaptor() _NOEXCEPT {} 426 template <class _OuterA2, 427 class = typename enable_if< 428 is_constructible<outer_allocator_type, _OuterA2>::value 429 >::type> 430 _LIBCPP_INLINE_VISIBILITY 431 scoped_allocator_adaptor(_OuterA2&& __outerAlloc, 432 const _InnerAllocs& ...__innerAllocs) _NOEXCEPT 433 : base(_VSTD::forward<_OuterA2>(__outerAlloc), __innerAllocs...) {} 434 // scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) = default; 435 template <class _OuterA2, 436 class = typename enable_if< 437 is_constructible<outer_allocator_type, const _OuterA2&>::value 438 >::type> 439 _LIBCPP_INLINE_VISIBILITY 440 scoped_allocator_adaptor( 441 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT 442 : base(__other) {} 443 template <class _OuterA2, 444 class = typename enable_if< 445 is_constructible<outer_allocator_type, _OuterA2>::value 446 >::type> 447 _LIBCPP_INLINE_VISIBILITY 448 scoped_allocator_adaptor( 449 scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT 450 : base(_VSTD::move(__other)) {} 451 452 // ~scoped_allocator_adaptor() = default; 453 454 _LIBCPP_INLINE_VISIBILITY 455 inner_allocator_type& inner_allocator() _NOEXCEPT 456 {return base::inner_allocator();} 457 _LIBCPP_INLINE_VISIBILITY 458 const inner_allocator_type& inner_allocator() const _NOEXCEPT 459 {return base::inner_allocator();} 460 461 _LIBCPP_INLINE_VISIBILITY 462 outer_allocator_type& outer_allocator() _NOEXCEPT 463 {return base::outer_allocator();} 464 _LIBCPP_INLINE_VISIBILITY 465 const outer_allocator_type& outer_allocator() const _NOEXCEPT 466 {return base::outer_allocator();} 467 468 _LIBCPP_INLINE_VISIBILITY 469 pointer allocate(size_type __n) 470 {return allocator_traits<outer_allocator_type>:: 471 allocate(outer_allocator(), __n);} 472 _LIBCPP_INLINE_VISIBILITY 473 pointer allocate(size_type __n, const_void_pointer __hint) 474 {return allocator_traits<outer_allocator_type>:: 475 allocate(outer_allocator(), __n, __hint);} 476 477 _LIBCPP_INLINE_VISIBILITY 478 void deallocate(pointer __p, size_type __n) _NOEXCEPT 479 {allocator_traits<outer_allocator_type>:: 480 deallocate(outer_allocator(), __p, __n);} 481 482 _LIBCPP_INLINE_VISIBILITY 483 size_type max_size() const 484 {return allocator_traits<outer_allocator_type>::max_size(outer_allocator());} 485 486 template <class _Tp, class... _Args> 487 _LIBCPP_INLINE_VISIBILITY 488 void construct(_Tp* __p, _Args&& ...__args) 489 {__construct(__uses_alloc_ctor<_Tp, inner_allocator_type, _Args...>(), 490 __p, _VSTD::forward<_Args>(__args)...);} 491 template <class _Tp> 492 _LIBCPP_INLINE_VISIBILITY 493 void destroy(_Tp* __p) 494 { 495 typedef __outermost<outer_allocator_type> _OM; 496 allocator_traits<typename _OM::type>:: 497 destroy(_OM()(outer_allocator()), __p); 498 } 499 500 _LIBCPP_INLINE_VISIBILITY 501 scoped_allocator_adaptor select_on_container_copy_construction() const _NOEXCEPT 502 {return base::select_on_container_copy_construction();} 503 504private: 505 506 template <class _OuterA2, 507 class = typename enable_if< 508 is_constructible<outer_allocator_type, _OuterA2>::value 509 >::type> 510 _LIBCPP_INLINE_VISIBILITY 511 scoped_allocator_adaptor(_OuterA2&& __o, 512 const inner_allocator_type& __i) _NOEXCEPT 513 : base(_VSTD::forward<_OuterA2>(__o), __i) {} 514 515 template <class _Tp, class... _Args> 516 _LIBCPP_INLINE_VISIBILITY 517 void __construct(integral_constant<int, 0>, _Tp* __p, _Args&& ...__args) 518 { 519 typedef __outermost<outer_allocator_type> _OM; 520 allocator_traits<typename _OM::type>::construct 521 ( 522 _OM()(outer_allocator()), 523 __p, 524 _VSTD::forward<_Args>(__args)... 525 ); 526 } 527 528 template <class _Tp, class... _Args> 529 _LIBCPP_INLINE_VISIBILITY 530 void __construct(integral_constant<int, 1>, _Tp* __p, _Args&& ...__args) 531 { 532 typedef __outermost<outer_allocator_type> _OM; 533 allocator_traits<typename _OM::type>::construct 534 ( 535 _OM()(outer_allocator()), 536 __p, 537 allocator_arg, 538 inner_allocator(), 539 _VSTD::forward<_Args>(__args)... 540 ); 541 } 542 543 template <class _Tp, class... _Args> 544 _LIBCPP_INLINE_VISIBILITY 545 void __construct(integral_constant<int, 2>, _Tp* __p, _Args&& ...__args) 546 { 547 typedef __outermost<outer_allocator_type> _OM; 548 allocator_traits<typename _OM::type>::construct 549 ( 550 _OM()(outer_allocator()), 551 __p, 552 _VSTD::forward<_Args>(__args)..., 553 inner_allocator() 554 ); 555 } 556 557 template <class...> friend class __scoped_allocator_storage; 558}; 559 560template <class _OuterA1, class _OuterA2> 561inline _LIBCPP_INLINE_VISIBILITY 562bool 563operator==(const scoped_allocator_adaptor<_OuterA1>& __a, 564 const scoped_allocator_adaptor<_OuterA2>& __b) _NOEXCEPT 565{ 566 return __a.outer_allocator() == __b.outer_allocator(); 567} 568 569template <class _OuterA1, class _OuterA2, class _InnerA0, class... _InnerAllocs> 570inline _LIBCPP_INLINE_VISIBILITY 571bool 572operator==(const scoped_allocator_adaptor<_OuterA1, _InnerA0, _InnerAllocs...>& __a, 573 const scoped_allocator_adaptor<_OuterA2, _InnerA0, _InnerAllocs...>& __b) _NOEXCEPT 574{ 575 return __a.outer_allocator() == __b.outer_allocator() && 576 __a.inner_allocator() == __b.inner_allocator(); 577} 578 579template <class _OuterA1, class _OuterA2, class... _InnerAllocs> 580inline _LIBCPP_INLINE_VISIBILITY 581bool 582operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a, 583 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __b) _NOEXCEPT 584{ 585 return !(__a == __b); 586} 587 588#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_ADVANCED_SFINAE) 589 590_LIBCPP_END_NAMESPACE_STD 591 592#endif // _LIBCPP_SCOPED_ALLOCATOR 593