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