10b57cec5SDimitry Andric// -*- C++ -*- 2349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 30b57cec5SDimitry Andric// 40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric// 80b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric#ifndef _LIBCPP_SCOPED_ALLOCATOR 110b57cec5SDimitry Andric#define _LIBCPP_SCOPED_ALLOCATOR 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric/* 140b57cec5SDimitry Andric scoped_allocator synopsis 150b57cec5SDimitry Andric 160b57cec5SDimitry Andricnamespace std 170b57cec5SDimitry Andric{ 180b57cec5SDimitry Andric 190b57cec5SDimitry Andrictemplate <class OuterAlloc, class... InnerAllocs> 200b57cec5SDimitry Andricclass scoped_allocator_adaptor : public OuterAlloc 210b57cec5SDimitry Andric{ 220b57cec5SDimitry Andric typedef allocator_traits<OuterAlloc> OuterTraits; // exposition only 230b57cec5SDimitry Andric scoped_allocator_adaptor<InnerAllocs...> inner; // exposition only 240b57cec5SDimitry Andricpublic: 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric typedef OuterAlloc outer_allocator_type; 270b57cec5SDimitry Andric typedef see below inner_allocator_type; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric typedef typename OuterTraits::value_type value_type; 300b57cec5SDimitry Andric typedef typename OuterTraits::size_type size_type; 310b57cec5SDimitry Andric typedef typename OuterTraits::difference_type difference_type; 320b57cec5SDimitry Andric typedef typename OuterTraits::pointer pointer; 330b57cec5SDimitry Andric typedef typename OuterTraits::const_pointer const_pointer; 340b57cec5SDimitry Andric typedef typename OuterTraits::void_pointer void_pointer; 350b57cec5SDimitry Andric typedef typename OuterTraits::const_void_pointer const_void_pointer; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric typedef see below propagate_on_container_copy_assignment; 380b57cec5SDimitry Andric typedef see below propagate_on_container_move_assignment; 390b57cec5SDimitry Andric typedef see below propagate_on_container_swap; 400b57cec5SDimitry Andric typedef see below is_always_equal; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric template <class Tp> 430b57cec5SDimitry Andric struct rebind 440b57cec5SDimitry Andric { 450b57cec5SDimitry Andric typedef scoped_allocator_adaptor< 460b57cec5SDimitry Andric OuterTraits::template rebind_alloc<Tp>, InnerAllocs...> other; 470b57cec5SDimitry Andric }; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric scoped_allocator_adaptor(); 500b57cec5SDimitry Andric template <class OuterA2> 510b57cec5SDimitry Andric scoped_allocator_adaptor(OuterA2&& outerAlloc, 520b57cec5SDimitry Andric const InnerAllocs&... innerAllocs) noexcept; 530b57cec5SDimitry Andric scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; 540b57cec5SDimitry Andric scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; 550b57cec5SDimitry Andric template <class OuterA2> 560b57cec5SDimitry Andric scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept; 570b57cec5SDimitry Andric template <class OuterA2> 580b57cec5SDimitry Andric scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default; 610b57cec5SDimitry Andric scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default; 620b57cec5SDimitry Andric ~scoped_allocator_adaptor(); 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric inner_allocator_type& inner_allocator() noexcept; 650b57cec5SDimitry Andric const inner_allocator_type& inner_allocator() const noexcept; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric outer_allocator_type& outer_allocator() noexcept; 680b57cec5SDimitry Andric const outer_allocator_type& outer_allocator() const noexcept; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric pointer allocate(size_type n); // [[nodiscard]] in C++20 710b57cec5SDimitry Andric pointer allocate(size_type n, const_void_pointer hint); // [[nodiscard]] in C++20 720b57cec5SDimitry Andric void deallocate(pointer p, size_type n) noexcept; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric size_type max_size() const; 750b57cec5SDimitry Andric template <class T, class... Args> void construct(T* p, Args&& args); 760b57cec5SDimitry Andric template <class T1, class T2, class... Args1, class... Args2> 770b57cec5SDimitry Andric void construct(pair<T1, T2>* p, piecewise_construct t, tuple<Args1...> x, 780b57cec5SDimitry Andric tuple<Args2...> y); 790b57cec5SDimitry Andric template <class T1, class T2> 800b57cec5SDimitry Andric void construct(pair<T1, T2>* p); 810b57cec5SDimitry Andric template <class T1, class T2, class U, class V> 820b57cec5SDimitry Andric void construct(pair<T1, T2>* p, U&& x, V&& y); 830b57cec5SDimitry Andric template <class T1, class T2, class U, class V> 840b57cec5SDimitry Andric void construct(pair<T1, T2>* p, const pair<U, V>& x); 850b57cec5SDimitry Andric template <class T1, class T2, class U, class V> 860b57cec5SDimitry Andric void construct(pair<T1, T2>* p, pair<U, V>&& x); 870b57cec5SDimitry Andric template <class T> void destroy(T* p); 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric template <class T> void destroy(T* p) noexcept; 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric scoped_allocator_adaptor select_on_container_copy_construction() const noexcept; 920b57cec5SDimitry Andric}; 930b57cec5SDimitry Andric 94349cc55cSDimitry Andrictemplate<class OuterAlloc, class... InnerAllocs> 95349cc55cSDimitry Andric scoped_allocator_adaptor(OuterAlloc, InnerAllocs...) 96349cc55cSDimitry Andric -> scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>; 97349cc55cSDimitry Andric 980b57cec5SDimitry Andrictemplate <class OuterA1, class OuterA2, class... InnerAllocs> 990b57cec5SDimitry Andric bool 1000b57cec5SDimitry Andric operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, 1010b57cec5SDimitry Andric const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andrictemplate <class OuterA1, class OuterA2, class... InnerAllocs> 1040b57cec5SDimitry Andric bool 1050b57cec5SDimitry Andric operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, 10606c3fb27SDimitry Andric const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept; // removed in C++20 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric} // std 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric*/ 1110b57cec5SDimitry Andric 11281ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler 1130b57cec5SDimitry Andric#include <__config> 114bdd1243dSDimitry Andric#include <__memory/allocator_traits.h> 115bdd1243dSDimitry Andric#include <__memory/uses_allocator_construction.h> 116bdd1243dSDimitry Andric#include <__type_traits/common_type.h> 117bdd1243dSDimitry Andric#include <__type_traits/enable_if.h> 118bdd1243dSDimitry Andric#include <__type_traits/integral_constant.h> 119bdd1243dSDimitry Andric#include <__type_traits/is_constructible.h> 120bdd1243dSDimitry Andric#include <__type_traits/remove_reference.h> 121bdd1243dSDimitry Andric#include <__utility/declval.h> 122fe6060f1SDimitry Andric#include <__utility/forward.h> 123bdd1243dSDimitry Andric#include <__utility/move.h> 124bdd1243dSDimitry Andric#include <__utility/pair.h> 125bdd1243dSDimitry Andric#include <__utility/piecewise_construct.h> 126bdd1243dSDimitry Andric#include <tuple> 1270b57cec5SDimitry Andric#include <version> 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1300b57cec5SDimitry Andric# pragma GCC system_header 1310b57cec5SDimitry Andric#endif 1320b57cec5SDimitry Andric 13306c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS 13406c3fb27SDimitry Andric#include <__undef_macros> 13506c3fb27SDimitry Andric 1360b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric#if !defined(_LIBCPP_CXX03_LANG) 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric// scoped_allocator_adaptor 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andrictemplate <class... _Allocs> 1430b57cec5SDimitry Andricclass scoped_allocator_adaptor; 1440b57cec5SDimitry Andric 145*cb14a3feSDimitry Andrictemplate <class... _Allocs> 146*cb14a3feSDimitry Andricstruct __get_poc_copy_assignment; 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andrictemplate <class _A0> 149*cb14a3feSDimitry Andricstruct __get_poc_copy_assignment<_A0> { 150*cb14a3feSDimitry Andric static const bool value = allocator_traits<_A0>::propagate_on_container_copy_assignment::value; 1510b57cec5SDimitry Andric}; 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andrictemplate <class _A0, class... _Allocs> 154*cb14a3feSDimitry Andricstruct __get_poc_copy_assignment<_A0, _Allocs...> { 155*cb14a3feSDimitry Andric static const bool value = allocator_traits<_A0>::propagate_on_container_copy_assignment::value || 1560b57cec5SDimitry Andric __get_poc_copy_assignment<_Allocs...>::value; 1570b57cec5SDimitry Andric}; 1580b57cec5SDimitry Andric 159*cb14a3feSDimitry Andrictemplate <class... _Allocs> 160*cb14a3feSDimitry Andricstruct __get_poc_move_assignment; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andrictemplate <class _A0> 163*cb14a3feSDimitry Andricstruct __get_poc_move_assignment<_A0> { 164*cb14a3feSDimitry Andric static const bool value = allocator_traits<_A0>::propagate_on_container_move_assignment::value; 1650b57cec5SDimitry Andric}; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andrictemplate <class _A0, class... _Allocs> 168*cb14a3feSDimitry Andricstruct __get_poc_move_assignment<_A0, _Allocs...> { 169*cb14a3feSDimitry Andric static const bool value = allocator_traits<_A0>::propagate_on_container_move_assignment::value || 1700b57cec5SDimitry Andric __get_poc_move_assignment<_Allocs...>::value; 1710b57cec5SDimitry Andric}; 1720b57cec5SDimitry Andric 173*cb14a3feSDimitry Andrictemplate <class... _Allocs> 174*cb14a3feSDimitry Andricstruct __get_poc_swap; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andrictemplate <class _A0> 177*cb14a3feSDimitry Andricstruct __get_poc_swap<_A0> { 178*cb14a3feSDimitry Andric static const bool value = allocator_traits<_A0>::propagate_on_container_swap::value; 1790b57cec5SDimitry Andric}; 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andrictemplate <class _A0, class... _Allocs> 182*cb14a3feSDimitry Andricstruct __get_poc_swap<_A0, _Allocs...> { 1830b57cec5SDimitry Andric static const bool value = 184*cb14a3feSDimitry Andric allocator_traits<_A0>::propagate_on_container_swap::value || __get_poc_swap<_Allocs...>::value; 1850b57cec5SDimitry Andric}; 1860b57cec5SDimitry Andric 187*cb14a3feSDimitry Andrictemplate <class... _Allocs> 188*cb14a3feSDimitry Andricstruct __get_is_always_equal; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andrictemplate <class _A0> 191*cb14a3feSDimitry Andricstruct __get_is_always_equal<_A0> { 1920b57cec5SDimitry Andric static const bool value = allocator_traits<_A0>::is_always_equal::value; 1930b57cec5SDimitry Andric}; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andrictemplate <class _A0, class... _Allocs> 196*cb14a3feSDimitry Andricstruct __get_is_always_equal<_A0, _Allocs...> { 197*cb14a3feSDimitry Andric static const bool value = allocator_traits<_A0>::is_always_equal::value && __get_is_always_equal<_Allocs...>::value; 1980b57cec5SDimitry Andric}; 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andrictemplate <class... _Allocs> 2010b57cec5SDimitry Andricclass __scoped_allocator_storage; 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andrictemplate <class _OuterAlloc, class... _InnerAllocs> 204*cb14a3feSDimitry Andricclass __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> : public _OuterAlloc { 2050b57cec5SDimitry Andric typedef _OuterAlloc outer_allocator_type; 206*cb14a3feSDimitry Andric 2070b57cec5SDimitry Andricprotected: 2080b57cec5SDimitry Andric typedef scoped_allocator_adaptor<_InnerAllocs...> inner_allocator_type; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andricprivate: 2110b57cec5SDimitry Andric inner_allocator_type __inner_; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andricprotected: 214*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage() _NOEXCEPT {} 2150b57cec5SDimitry Andric 216*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0> 2175f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 218*cb14a3feSDimitry Andric __scoped_allocator_storage(_OuterA2&& __outer_alloc, const _InnerAllocs&... __inner_allocs) _NOEXCEPT 2195f757f3fSDimitry Andric : outer_allocator_type(std::forward<_OuterA2>(__outer_alloc)), 220753f127fSDimitry Andric __inner_(__inner_allocs...) {} 2210b57cec5SDimitry Andric 222*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, const _OuterA2&>::value, int> = 0> 2235f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 224*cb14a3feSDimitry Andric __scoped_allocator_storage(const __scoped_allocator_storage<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT 2250b57cec5SDimitry Andric : outer_allocator_type(__other.outer_allocator()), 2260b57cec5SDimitry Andric __inner_(__other.inner_allocator()) {} 2270b57cec5SDimitry Andric 228*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0> 2295f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 230*cb14a3feSDimitry Andric __scoped_allocator_storage(__scoped_allocator_storage<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT 2315f757f3fSDimitry Andric : outer_allocator_type(std::move(__other.outer_allocator())), 2325f757f3fSDimitry Andric __inner_(std::move(__other.inner_allocator())) {} 2330b57cec5SDimitry Andric 234*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0> 235*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage(_OuterA2&& __o, const inner_allocator_type& __i) _NOEXCEPT 2365f757f3fSDimitry Andric : outer_allocator_type(std::forward<_OuterA2>(__o)), 237*cb14a3feSDimitry Andric __inner_(__i) {} 238*cb14a3feSDimitry Andric 239*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inner_allocator_type& inner_allocator() _NOEXCEPT { return __inner_; } 240*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI const inner_allocator_type& inner_allocator() const _NOEXCEPT { return __inner_; } 241*cb14a3feSDimitry Andric 242*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI outer_allocator_type& outer_allocator() _NOEXCEPT { 243*cb14a3feSDimitry Andric return static_cast<outer_allocator_type&>(*this); 244*cb14a3feSDimitry Andric } 245*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI const outer_allocator_type& outer_allocator() const _NOEXCEPT { 246*cb14a3feSDimitry Andric return static_cast<const outer_allocator_type&>(*this); 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 249*cb14a3feSDimitry Andric scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...> _LIBCPP_HIDE_FROM_ABI 250*cb14a3feSDimitry Andric select_on_container_copy_construction() const _NOEXCEPT { 251*cb14a3feSDimitry Andric return scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>( 252*cb14a3feSDimitry Andric allocator_traits<outer_allocator_type>::select_on_container_copy_construction(outer_allocator()), 253*cb14a3feSDimitry Andric allocator_traits<inner_allocator_type>::select_on_container_copy_construction(inner_allocator())); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 256*cb14a3feSDimitry Andric template <class...> 257*cb14a3feSDimitry Andric friend class __scoped_allocator_storage; 2580b57cec5SDimitry Andric}; 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andrictemplate <class _OuterAlloc> 261*cb14a3feSDimitry Andricclass __scoped_allocator_storage<_OuterAlloc> : public _OuterAlloc { 2620b57cec5SDimitry Andric typedef _OuterAlloc outer_allocator_type; 263*cb14a3feSDimitry Andric 2640b57cec5SDimitry Andricprotected: 2650b57cec5SDimitry Andric typedef scoped_allocator_adaptor<_OuterAlloc> inner_allocator_type; 2660b57cec5SDimitry Andric 267*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage() _NOEXCEPT {} 2680b57cec5SDimitry Andric 269*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0> 270*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage(_OuterA2&& __outer_alloc) _NOEXCEPT 2715f757f3fSDimitry Andric : outer_allocator_type(std::forward<_OuterA2>(__outer_alloc)) {} 2720b57cec5SDimitry Andric 273*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, const _OuterA2&>::value, int> = 0> 274*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage(const __scoped_allocator_storage<_OuterA2>& __other) _NOEXCEPT 2750b57cec5SDimitry Andric : outer_allocator_type(__other.outer_allocator()) {} 2760b57cec5SDimitry Andric 277*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0> 278*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage(__scoped_allocator_storage<_OuterA2>&& __other) _NOEXCEPT 2795f757f3fSDimitry Andric : outer_allocator_type(std::move(__other.outer_allocator())) {} 2800b57cec5SDimitry Andric 281*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inner_allocator_type& inner_allocator() _NOEXCEPT { 282*cb14a3feSDimitry Andric return static_cast<inner_allocator_type&>(*this); 283*cb14a3feSDimitry Andric } 284*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI const inner_allocator_type& inner_allocator() const _NOEXCEPT { 285*cb14a3feSDimitry Andric return static_cast<const inner_allocator_type&>(*this); 286*cb14a3feSDimitry Andric } 2870b57cec5SDimitry Andric 288*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI outer_allocator_type& outer_allocator() _NOEXCEPT { 289*cb14a3feSDimitry Andric return static_cast<outer_allocator_type&>(*this); 290*cb14a3feSDimitry Andric } 291*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI const outer_allocator_type& outer_allocator() const _NOEXCEPT { 292*cb14a3feSDimitry Andric return static_cast<const outer_allocator_type&>(*this); 293*cb14a3feSDimitry Andric } 2940b57cec5SDimitry Andric 295*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI scoped_allocator_adaptor<outer_allocator_type> 296*cb14a3feSDimitry Andric select_on_container_copy_construction() const _NOEXCEPT { 297*cb14a3feSDimitry Andric return scoped_allocator_adaptor<outer_allocator_type>( 298*cb14a3feSDimitry Andric allocator_traits<outer_allocator_type>::select_on_container_copy_construction(outer_allocator())); 299*cb14a3feSDimitry Andric } 3000b57cec5SDimitry Andric 301*cb14a3feSDimitry Andric __scoped_allocator_storage(const outer_allocator_type& __o, const inner_allocator_type& __i) _NOEXCEPT; 3020b57cec5SDimitry Andric 303*cb14a3feSDimitry Andric template <class...> 304*cb14a3feSDimitry Andric friend class __scoped_allocator_storage; 3050b57cec5SDimitry Andric}; 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric// __outermost 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andrictemplate <class _Alloc> 310*cb14a3feSDimitry Andricdecltype(std::declval<_Alloc>().outer_allocator(), true_type()) __has_outer_allocator_test(_Alloc&& __a); 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andrictemplate <class _Alloc> 313*cb14a3feSDimitry Andricfalse_type __has_outer_allocator_test(const volatile _Alloc& __a); 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andrictemplate <class _Alloc> 3160b57cec5SDimitry Andricstruct __has_outer_allocator 317*cb14a3feSDimitry Andric : public common_type< decltype(std::__has_outer_allocator_test(std::declval<_Alloc&>())) >::type {}; 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andrictemplate <class _Alloc, bool = __has_outer_allocator<_Alloc>::value> 320*cb14a3feSDimitry Andricstruct __outermost { 3210b57cec5SDimitry Andric typedef _Alloc type; 322*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI type& operator()(type& __a) const _NOEXCEPT { return __a; } 3230b57cec5SDimitry Andric}; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andrictemplate <class _Alloc> 326*cb14a3feSDimitry Andricstruct __outermost<_Alloc, true> { 327*cb14a3feSDimitry Andric typedef __libcpp_remove_reference_t< decltype(std::declval<_Alloc>().outer_allocator()) > _OuterAlloc; 3280b57cec5SDimitry Andric typedef typename __outermost<_OuterAlloc>::type type; 329*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI type& operator()(_Alloc& __a) const _NOEXCEPT { 330*cb14a3feSDimitry Andric return __outermost<_OuterAlloc>()(__a.outer_allocator()); 331*cb14a3feSDimitry Andric } 3320b57cec5SDimitry Andric}; 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andrictemplate <class _OuterAlloc, class... _InnerAllocs> 3350b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...> 336*cb14a3feSDimitry Andric : public __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> { 3370b57cec5SDimitry Andric typedef __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> base; 3380b57cec5SDimitry Andric typedef allocator_traits<_OuterAlloc> _OuterTraits; 339*cb14a3feSDimitry Andric 3400b57cec5SDimitry Andricpublic: 3410b57cec5SDimitry Andric typedef _OuterAlloc outer_allocator_type; 3420b57cec5SDimitry Andric typedef typename base::inner_allocator_type inner_allocator_type; 3430b57cec5SDimitry Andric typedef typename _OuterTraits::size_type size_type; 3440b57cec5SDimitry Andric typedef typename _OuterTraits::difference_type difference_type; 3450b57cec5SDimitry Andric typedef typename _OuterTraits::pointer pointer; 3460b57cec5SDimitry Andric typedef typename _OuterTraits::const_pointer const_pointer; 3470b57cec5SDimitry Andric typedef typename _OuterTraits::void_pointer void_pointer; 3480b57cec5SDimitry Andric typedef typename _OuterTraits::const_void_pointer const_void_pointer; 3490b57cec5SDimitry Andric 350*cb14a3feSDimitry Andric typedef integral_constant< bool, __get_poc_copy_assignment<outer_allocator_type, _InnerAllocs...>::value > 351*cb14a3feSDimitry Andric propagate_on_container_copy_assignment; 352*cb14a3feSDimitry Andric typedef integral_constant< bool, __get_poc_move_assignment<outer_allocator_type, _InnerAllocs...>::value > 353*cb14a3feSDimitry Andric propagate_on_container_move_assignment; 354*cb14a3feSDimitry Andric typedef integral_constant< bool, __get_poc_swap<outer_allocator_type, _InnerAllocs...>::value > 355*cb14a3feSDimitry Andric propagate_on_container_swap; 356*cb14a3feSDimitry Andric typedef integral_constant< bool, __get_is_always_equal<outer_allocator_type, _InnerAllocs...>::value > 357*cb14a3feSDimitry Andric is_always_equal; 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric template <class _Tp> 360*cb14a3feSDimitry Andric struct rebind { 361*cb14a3feSDimitry Andric typedef scoped_allocator_adaptor< typename _OuterTraits::template rebind_alloc<_Tp>, _InnerAllocs... > other; 3620b57cec5SDimitry Andric }; 3630b57cec5SDimitry Andric 364*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI scoped_allocator_adaptor() _NOEXCEPT {} 365*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0> 3665f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 367*cb14a3feSDimitry Andric scoped_allocator_adaptor(_OuterA2&& __outer_alloc, const _InnerAllocs&... __inner_allocs) _NOEXCEPT 3685f757f3fSDimitry Andric : base(std::forward<_OuterA2>(__outer_alloc), __inner_allocs...) {} 3690b57cec5SDimitry Andric // scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) = default; 370*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, const _OuterA2&>::value, int> = 0> 3715f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 372*cb14a3feSDimitry Andric scoped_allocator_adaptor(const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT 3730b57cec5SDimitry Andric : base(__other) {} 374*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0> 3755f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 376*cb14a3feSDimitry Andric scoped_allocator_adaptor(scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT 3775f757f3fSDimitry Andric : base(std::move(__other)) {} 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric // scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default; 3800b57cec5SDimitry Andric // scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default; 3810b57cec5SDimitry Andric // ~scoped_allocator_adaptor() = default; 3820b57cec5SDimitry Andric 383*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inner_allocator_type& inner_allocator() _NOEXCEPT { return base::inner_allocator(); } 384*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI const inner_allocator_type& inner_allocator() const _NOEXCEPT { 385*cb14a3feSDimitry Andric return base::inner_allocator(); 386*cb14a3feSDimitry Andric } 3870b57cec5SDimitry Andric 388*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI outer_allocator_type& outer_allocator() _NOEXCEPT { return base::outer_allocator(); } 389*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI const outer_allocator_type& outer_allocator() const _NOEXCEPT { 390*cb14a3feSDimitry Andric return base::outer_allocator(); 391*cb14a3feSDimitry Andric } 3920b57cec5SDimitry Andric 393*cb14a3feSDimitry Andric _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pointer allocate(size_type __n) { 394*cb14a3feSDimitry Andric return allocator_traits<outer_allocator_type>::allocate(outer_allocator(), __n); 395*cb14a3feSDimitry Andric } 396*cb14a3feSDimitry Andric _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pointer allocate(size_type __n, const_void_pointer __hint) { 397*cb14a3feSDimitry Andric return allocator_traits<outer_allocator_type>::allocate(outer_allocator(), __n, __hint); 398*cb14a3feSDimitry Andric } 3990b57cec5SDimitry Andric 400*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void deallocate(pointer __p, size_type __n) _NOEXCEPT { 401*cb14a3feSDimitry Andric allocator_traits<outer_allocator_type>::deallocate(outer_allocator(), __p, __n); 402*cb14a3feSDimitry Andric } 4030b57cec5SDimitry Andric 404*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type max_size() const { 405*cb14a3feSDimitry Andric return allocator_traits<outer_allocator_type>::max_size(outer_allocator()); 406*cb14a3feSDimitry Andric } 4070b57cec5SDimitry Andric 408bdd1243dSDimitry Andric# if _LIBCPP_STD_VER >= 20 409bdd1243dSDimitry Andric template <class _Type, class... _Args> 410bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI void construct(_Type* __ptr, _Args&&... __args) { 411bdd1243dSDimitry Andric using _OM = __outermost<outer_allocator_type>; 412bdd1243dSDimitry Andric std::apply( 413bdd1243dSDimitry Andric [__ptr, this](auto&&... __newargs) { 414bdd1243dSDimitry Andric allocator_traits<typename _OM::type>::construct( 415bdd1243dSDimitry Andric _OM()(outer_allocator()), __ptr, std::forward<decltype(__newargs)>(__newargs)...); 416bdd1243dSDimitry Andric }, 417bdd1243dSDimitry Andric std::uses_allocator_construction_args<_Type>(inner_allocator(), std::forward<_Args>(__args)...)); 418bdd1243dSDimitry Andric } 419bdd1243dSDimitry Andric# else 4200b57cec5SDimitry Andric template <class _Tp, class... _Args> 421*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void construct(_Tp* __p, _Args&&... __args) { 422*cb14a3feSDimitry Andric __construct(__uses_alloc_ctor<_Tp, inner_allocator_type&, _Args...>(), __p, std::forward<_Args>(__args)...); 423*cb14a3feSDimitry Andric } 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric template <class _T1, class _T2, class... _Args1, class... _Args2> 426*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void 427*cb14a3feSDimitry Andric construct(pair<_T1, _T2>* __p, piecewise_construct_t, tuple<_Args1...> __x, tuple<_Args2...> __y) { 4280b57cec5SDimitry Andric typedef __outermost<outer_allocator_type> _OM; 4290b57cec5SDimitry Andric allocator_traits<typename _OM::type>::construct( 430*cb14a3feSDimitry Andric _OM()(outer_allocator()), 431*cb14a3feSDimitry Andric __p, 432*cb14a3feSDimitry Andric piecewise_construct, 433*cb14a3feSDimitry Andric __transform_tuple(typename __uses_alloc_ctor< _T1, inner_allocator_type&, _Args1... >::type(), 434*cb14a3feSDimitry Andric std::move(__x), 435*cb14a3feSDimitry Andric typename __make_tuple_indices<sizeof...(_Args1)>::type{}), 436*cb14a3feSDimitry Andric __transform_tuple(typename __uses_alloc_ctor< _T2, inner_allocator_type&, _Args2... >::type(), 437*cb14a3feSDimitry Andric std::move(__y), 438*cb14a3feSDimitry Andric typename __make_tuple_indices<sizeof...(_Args2)>::type{})); 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric template <class _T1, class _T2> 442*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p) { 443*cb14a3feSDimitry Andric construct(__p, piecewise_construct, tuple<>{}, tuple<>{}); 444*cb14a3feSDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric template <class _T1, class _T2, class _Up, class _Vp> 44706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, _Up&& __x, _Vp&& __y) { 448*cb14a3feSDimitry Andric construct(__p, 449*cb14a3feSDimitry Andric piecewise_construct, 4505f757f3fSDimitry Andric std::forward_as_tuple(std::forward<_Up>(__x)), 4515f757f3fSDimitry Andric std::forward_as_tuple(std::forward<_Vp>(__y))); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric template <class _T1, class _T2, class _Up, class _Vp> 45506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) { 456*cb14a3feSDimitry Andric construct(__p, piecewise_construct, std::forward_as_tuple(__x.first), std::forward_as_tuple(__x.second)); 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric template <class _T1, class _T2, class _Up, class _Vp> 46006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) { 461*cb14a3feSDimitry Andric construct(__p, 462*cb14a3feSDimitry Andric piecewise_construct, 4635f757f3fSDimitry Andric std::forward_as_tuple(std::forward<_Up>(__x.first)), 4645f757f3fSDimitry Andric std::forward_as_tuple(std::forward<_Vp>(__x.second))); 4650b57cec5SDimitry Andric } 466bdd1243dSDimitry Andric# endif 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric template <class _Tp> 469*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void destroy(_Tp* __p) { 4700b57cec5SDimitry Andric typedef __outermost<outer_allocator_type> _OM; 471*cb14a3feSDimitry Andric allocator_traits<typename _OM::type>::destroy(_OM()(outer_allocator()), __p); 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric 474*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI scoped_allocator_adaptor select_on_container_copy_construction() const _NOEXCEPT { 475*cb14a3feSDimitry Andric return base::select_on_container_copy_construction(); 476*cb14a3feSDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andricprivate: 479*cb14a3feSDimitry Andric template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0> 480*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI scoped_allocator_adaptor(_OuterA2&& __o, const inner_allocator_type& __i) _NOEXCEPT 4815f757f3fSDimitry Andric : base(std::forward<_OuterA2>(__o), __i) {} 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric template <class _Tp, class... _Args> 484*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __construct(integral_constant<int, 0>, _Tp* __p, _Args&&... __args) { 4850b57cec5SDimitry Andric typedef __outermost<outer_allocator_type> _OM; 486*cb14a3feSDimitry Andric allocator_traits<typename _OM::type>::construct(_OM()(outer_allocator()), __p, std::forward<_Args>(__args)...); 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric template <class _Tp, class... _Args> 490*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __construct(integral_constant<int, 1>, _Tp* __p, _Args&&... __args) { 4910b57cec5SDimitry Andric typedef __outermost<outer_allocator_type> _OM; 492*cb14a3feSDimitry Andric allocator_traits<typename _OM::type>::construct( 493*cb14a3feSDimitry Andric _OM()(outer_allocator()), __p, allocator_arg, inner_allocator(), std::forward<_Args>(__args)...); 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric template <class _Tp, class... _Args> 497*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __construct(integral_constant<int, 2>, _Tp* __p, _Args&&... __args) { 4980b57cec5SDimitry Andric typedef __outermost<outer_allocator_type> _OM; 499*cb14a3feSDimitry Andric allocator_traits<typename _OM::type>::construct( 500*cb14a3feSDimitry Andric _OM()(outer_allocator()), __p, std::forward<_Args>(__args)..., inner_allocator()); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric template <class... _Args, size_t... _Idx> 504*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI tuple<_Args&&...> 505*cb14a3feSDimitry Andric __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, __tuple_indices<_Idx...>) { 5065f757f3fSDimitry Andric return std::forward_as_tuple(std::get<_Idx>(std::move(__t))...); 5070b57cec5SDimitry Andric } 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric template <class... _Args, size_t... _Idx> 510*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI tuple<allocator_arg_t, inner_allocator_type&, _Args&&...> 511*cb14a3feSDimitry Andric __transform_tuple(integral_constant<int, 1>, tuple<_Args...>&& __t, __tuple_indices<_Idx...>) { 5120b57cec5SDimitry Andric using _Tup = tuple<allocator_arg_t, inner_allocator_type&, _Args&&...>; 513*cb14a3feSDimitry Andric return _Tup(allocator_arg, inner_allocator(), std::get<_Idx>(std::move(__t))...); 5140b57cec5SDimitry Andric } 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric template <class... _Args, size_t... _Idx> 517*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI tuple<_Args&&..., inner_allocator_type&> 518*cb14a3feSDimitry Andric __transform_tuple(integral_constant<int, 2>, tuple<_Args...>&& __t, __tuple_indices<_Idx...>) { 5190b57cec5SDimitry Andric using _Tup = tuple<_Args&&..., inner_allocator_type&>; 5205f757f3fSDimitry Andric return _Tup(std::get<_Idx>(std::move(__t))..., inner_allocator()); 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric 523*cb14a3feSDimitry Andric template <class...> 524*cb14a3feSDimitry Andric friend class __scoped_allocator_storage; 5250b57cec5SDimitry Andric}; 5260b57cec5SDimitry Andric 52706c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 17 528349cc55cSDimitry Andrictemplate <class _OuterAlloc, class... _InnerAllocs> 529*cb14a3feSDimitry Andricscoped_allocator_adaptor(_OuterAlloc, _InnerAllocs...) -> scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>; 530349cc55cSDimitry Andric# endif 531349cc55cSDimitry Andric 5320b57cec5SDimitry Andrictemplate <class _OuterA1, class _OuterA2> 533*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI bool 534*cb14a3feSDimitry Andricoperator==(const scoped_allocator_adaptor<_OuterA1>& __a, const scoped_allocator_adaptor<_OuterA2>& __b) _NOEXCEPT { 5350b57cec5SDimitry Andric return __a.outer_allocator() == __b.outer_allocator(); 5360b57cec5SDimitry Andric} 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andrictemplate <class _OuterA1, class _OuterA2, class _InnerA0, class... _InnerAllocs> 539*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI bool 5400b57cec5SDimitry Andricoperator==(const scoped_allocator_adaptor<_OuterA1, _InnerA0, _InnerAllocs...>& __a, 541*cb14a3feSDimitry Andric const scoped_allocator_adaptor<_OuterA2, _InnerA0, _InnerAllocs...>& __b) _NOEXCEPT { 542*cb14a3feSDimitry Andric return __a.outer_allocator() == __b.outer_allocator() && __a.inner_allocator() == __b.inner_allocator(); 5430b57cec5SDimitry Andric} 5440b57cec5SDimitry Andric 54506c3fb27SDimitry Andric# if _LIBCPP_STD_VER <= 17 54606c3fb27SDimitry Andric 5470b57cec5SDimitry Andrictemplate <class _OuterA1, class _OuterA2, class... _InnerAllocs> 548*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI bool operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a, 549*cb14a3feSDimitry Andric const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __b) _NOEXCEPT { 5500b57cec5SDimitry Andric return !(__a == __b); 5510b57cec5SDimitry Andric} 5520b57cec5SDimitry Andric 55306c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER <= 17 55406c3fb27SDimitry Andric 5550b57cec5SDimitry Andric#endif // !defined(_LIBCPP_CXX03_LANG) 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 5580b57cec5SDimitry Andric 55906c3fb27SDimitry Andric_LIBCPP_POP_MACROS 56006c3fb27SDimitry Andric 561bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 562bdd1243dSDimitry Andric# include <atomic> 563bdd1243dSDimitry Andric# include <climits> 564bdd1243dSDimitry Andric# include <concepts> 565bdd1243dSDimitry Andric# include <cstring> 566bdd1243dSDimitry Andric# include <ctime> 567bdd1243dSDimitry Andric# include <iterator> 568bdd1243dSDimitry Andric# include <memory> 569bdd1243dSDimitry Andric# include <ratio> 570bdd1243dSDimitry Andric# include <stdexcept> 571bdd1243dSDimitry Andric# include <type_traits> 572bdd1243dSDimitry Andric# include <variant> 573bdd1243dSDimitry Andric#endif 574bdd1243dSDimitry Andric 5750b57cec5SDimitry Andric#endif // _LIBCPP_SCOPED_ALLOCATOR 576