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