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