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