Home | History | Annotate | Download | only in include
      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 
     17 namespace std
     18 {
     19 
     20 template <class OuterAlloc, class... InnerAllocs>
     21 class scoped_allocator_adaptor : public OuterAlloc
     22 {
     23     typedef allocator_traits<OuterAlloc> OuterTraits; // exposition only
     24     scoped_allocator_adaptor<InnerAllocs...> inner;   // exposition only
     25 public:
     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);                           // [[nodiscard]] in C++20
     72     pointer allocate(size_type n, const_void_pointer hint);  // [[nodiscard]] in C++20
     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 
     95 template <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 
    100 template <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_CXX03_LANG)
    119 
    120 // scoped_allocator_adaptor
    121 
    122 template <class ..._Allocs>
    123 class scoped_allocator_adaptor;
    124 
    125 template <class ..._Allocs> struct __get_poc_copy_assignment;
    126 
    127 template <class _A0>
    128 struct __get_poc_copy_assignment<_A0>
    129 {
    130     static const bool value = allocator_traits<_A0>::
    131                               propagate_on_container_copy_assignment::value;
    132 };
    133 
    134 template <class _A0, class ..._Allocs>
    135 struct __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 
    142 template <class ..._Allocs> struct __get_poc_move_assignment;
    143 
    144 template <class _A0>
    145 struct __get_poc_move_assignment<_A0>
    146 {
    147     static const bool value = allocator_traits<_A0>::
    148                               propagate_on_container_move_assignment::value;
    149 };
    150 
    151 template <class _A0, class ..._Allocs>
    152 struct __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 
    159 template <class ..._Allocs> struct __get_poc_swap;
    160 
    161 template <class _A0>
    162 struct __get_poc_swap<_A0>
    163 {
    164     static const bool value = allocator_traits<_A0>::
    165                               propagate_on_container_swap::value;
    166 };
    167 
    168 template <class _A0, class ..._Allocs>
    169 struct __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 
    176 template <class ..._Allocs> struct __get_is_always_equal;
    177 
    178 template <class _A0>
    179 struct __get_is_always_equal<_A0>
    180 {
    181     static const bool value = allocator_traits<_A0>::is_always_equal::value;
    182 };
    183 
    184 template <class _A0, class ..._Allocs>
    185 struct __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 
    192 template <class ..._Allocs>
    193 class __scoped_allocator_storage;
    194 
    195 template <class _OuterAlloc, class... _InnerAllocs>
    196 class __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...>
    197     : public _OuterAlloc
    198 {
    199     typedef _OuterAlloc outer_allocator_type;
    200 protected:
    201     typedef scoped_allocator_adaptor<_InnerAllocs...> inner_allocator_type;
    202 
    203 private:
    204     inner_allocator_type __inner_;
    205 
    206 protected:
    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 
    281 template <class _OuterAlloc>
    282 class __scoped_allocator_storage<_OuterAlloc>
    283     : public _OuterAlloc
    284 {
    285     typedef _OuterAlloc outer_allocator_type;
    286 protected:
    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 
    348 template <class _Alloc>
    349 decltype(declval<_Alloc>().outer_allocator(), true_type())
    350 __has_outer_allocator_test(_Alloc&& __a);
    351 
    352 template <class _Alloc>
    353 false_type
    354 __has_outer_allocator_test(const volatile _Alloc& __a);
    355 
    356 template <class _Alloc>
    357 struct __has_outer_allocator
    358     : public common_type
    359              <
    360                  decltype(__has_outer_allocator_test(declval<_Alloc&>()))
    361              >::type
    362 {
    363 };
    364 
    365 template <class _Alloc, bool = __has_outer_allocator<_Alloc>::value>
    366 struct __outermost
    367 {
    368     typedef _Alloc type;
    369     _LIBCPP_INLINE_VISIBILITY
    370     type& operator()(type& __a) const _NOEXCEPT {return __a;}
    371 };
    372 
    373 template <class _Alloc>
    374 struct __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 
    386 template <class _OuterAlloc, class... _InnerAllocs>
    387 class _LIBCPP_TEMPLATE_VIS 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;
    392 public:
    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_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
    481     pointer allocate(size_type __n)
    482         {return allocator_traits<outer_allocator_type>::
    483             allocate(outer_allocator(), __n);}
    484     _LIBCPP_NODISCARD_AFTER_CXX17 _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 
    504     template <class _T1, class _T2, class... _Args1, class... _Args2>
    505     void construct(pair<_T1, _T2>* __p, piecewise_construct_t,
    506                        tuple<_Args1...> __x, tuple<_Args2...> __y)
    507     {
    508         typedef __outermost<outer_allocator_type> _OM;
    509         allocator_traits<typename _OM::type>::construct(
    510             _OM()(outer_allocator()), __p, piecewise_construct
    511           , __transform_tuple(
    512               typename __uses_alloc_ctor<
    513                   _T1, inner_allocator_type&, _Args1...
    514               >::type()
    515             , _VSTD::move(__x)
    516             , typename __make_tuple_indices<sizeof...(_Args1)>::type{}
    517           )
    518           , __transform_tuple(
    519               typename __uses_alloc_ctor<
    520                   _T2, inner_allocator_type&, _Args2...
    521               >::type()
    522             , _VSTD::move(__y)
    523             , typename __make_tuple_indices<sizeof...(_Args2)>::type{}
    524           )
    525         );
    526     }
    527 
    528     template <class _T1, class _T2>
    529     void construct(pair<_T1, _T2>* __p)
    530     { construct(__p, piecewise_construct, tuple<>{}, tuple<>{}); }
    531 
    532     template <class _T1, class _T2, class _Up, class _Vp>
    533     void construct(pair<_T1, _T2>* __p, _Up&& __x, _Vp&& __y) {
    534         construct(__p, piecewise_construct,
    535                   _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__x)),
    536                   _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__y)));
    537     }
    538 
    539     template <class _T1, class _T2, class _Up, class _Vp>
    540     void construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) {
    541         construct(__p, piecewise_construct,
    542                   _VSTD::forward_as_tuple(__x.first),
    543                   _VSTD::forward_as_tuple(__x.second));
    544     }
    545 
    546     template <class _T1, class _T2, class _Up, class _Vp>
    547     void construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) {
    548         construct(__p, piecewise_construct,
    549                   _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__x.first)),
    550                   _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__x.second)));
    551     }
    552 
    553     template <class _Tp>
    554         _LIBCPP_INLINE_VISIBILITY
    555         void destroy(_Tp* __p)
    556             {
    557                 typedef __outermost<outer_allocator_type> _OM;
    558                 allocator_traits<typename _OM::type>::
    559                                          destroy(_OM()(outer_allocator()), __p);
    560             }
    561 
    562     _LIBCPP_INLINE_VISIBILITY
    563     scoped_allocator_adaptor select_on_container_copy_construction() const _NOEXCEPT
    564         {return base::select_on_container_copy_construction();}
    565 
    566 private:
    567 
    568 
    569     template <class _OuterA2,
    570               class = typename enable_if<
    571                         is_constructible<outer_allocator_type, _OuterA2>::value
    572                       >::type>
    573     _LIBCPP_INLINE_VISIBILITY
    574     scoped_allocator_adaptor(_OuterA2&& __o,
    575                              const inner_allocator_type& __i) _NOEXCEPT
    576         : base(_VSTD::forward<_OuterA2>(__o), __i) {}
    577 
    578     template <class _Tp, class... _Args>
    579         _LIBCPP_INLINE_VISIBILITY
    580         void __construct(integral_constant<int, 0>, _Tp* __p, _Args&& ...__args)
    581             {
    582                 typedef __outermost<outer_allocator_type> _OM;
    583                 allocator_traits<typename _OM::type>::construct
    584                 (
    585                     _OM()(outer_allocator()),
    586                     __p,
    587                     _VSTD::forward<_Args>(__args)...
    588                 );
    589             }
    590 
    591     template <class _Tp, class... _Args>
    592         _LIBCPP_INLINE_VISIBILITY
    593         void __construct(integral_constant<int, 1>, _Tp* __p, _Args&& ...__args)
    594             {
    595                 typedef __outermost<outer_allocator_type> _OM;
    596                 allocator_traits<typename _OM::type>::construct
    597                 (
    598                     _OM()(outer_allocator()),
    599                     __p, allocator_arg, inner_allocator(),
    600                     _VSTD::forward<_Args>(__args)...
    601                 );
    602             }
    603 
    604     template <class _Tp, class... _Args>
    605         _LIBCPP_INLINE_VISIBILITY
    606         void __construct(integral_constant<int, 2>, _Tp* __p, _Args&& ...__args)
    607             {
    608                 typedef __outermost<outer_allocator_type> _OM;
    609                 allocator_traits<typename _OM::type>::construct
    610                 (
    611                     _OM()(outer_allocator()),
    612                     __p,
    613                     _VSTD::forward<_Args>(__args)...,
    614                     inner_allocator()
    615                 );
    616             }
    617 
    618     template <class ..._Args, size_t ..._Idx>
    619     _LIBCPP_INLINE_VISIBILITY
    620     tuple<_Args&&...>
    621     __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t,
    622                       __tuple_indices<_Idx...>)
    623     {
    624         return _VSTD::forward_as_tuple(_VSTD::get<_Idx>(_VSTD::move(__t))...);
    625     }
    626 
    627     template <class ..._Args, size_t ..._Idx>
    628     _LIBCPP_INLINE_VISIBILITY
    629     tuple<allocator_arg_t, inner_allocator_type&, _Args&&...>
    630     __transform_tuple(integral_constant<int, 1>, tuple<_Args...> && __t,
    631                       __tuple_indices<_Idx...>)
    632     {
    633         using _Tup = tuple<allocator_arg_t, inner_allocator_type&, _Args&&...>;
    634         return _Tup(allocator_arg, inner_allocator(),
    635                     _VSTD::get<_Idx>(_VSTD::move(__t))...);
    636     }
    637 
    638     template <class ..._Args, size_t ..._Idx>
    639     _LIBCPP_INLINE_VISIBILITY
    640     tuple<_Args&&..., inner_allocator_type&>
    641     __transform_tuple(integral_constant<int, 2>, tuple<_Args...> && __t,
    642                       __tuple_indices<_Idx...>)
    643     {
    644         using _Tup = tuple<_Args&&..., inner_allocator_type&>;
    645         return _Tup(_VSTD::get<_Idx>(_VSTD::move(__t))..., inner_allocator());
    646     }
    647 
    648     template <class...> friend class __scoped_allocator_storage;
    649 };
    650 
    651 template <class _OuterA1, class _OuterA2>
    652 inline _LIBCPP_INLINE_VISIBILITY
    653 bool
    654 operator==(const scoped_allocator_adaptor<_OuterA1>& __a,
    655            const scoped_allocator_adaptor<_OuterA2>& __b) _NOEXCEPT
    656 {
    657     return __a.outer_allocator() == __b.outer_allocator();
    658 }
    659 
    660 template <class _OuterA1, class _OuterA2, class _InnerA0, class... _InnerAllocs>
    661 inline _LIBCPP_INLINE_VISIBILITY
    662 bool
    663 operator==(const scoped_allocator_adaptor<_OuterA1, _InnerA0, _InnerAllocs...>& __a,
    664            const scoped_allocator_adaptor<_OuterA2, _InnerA0, _InnerAllocs...>& __b) _NOEXCEPT
    665 {
    666     return __a.outer_allocator() == __b.outer_allocator() &&
    667            __a.inner_allocator() == __b.inner_allocator();
    668 }
    669 
    670 template <class _OuterA1, class _OuterA2, class... _InnerAllocs>
    671 inline _LIBCPP_INLINE_VISIBILITY
    672 bool
    673 operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a,
    674            const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __b) _NOEXCEPT
    675 {
    676     return !(__a == __b);
    677 }
    678 
    679 #endif  // !defined(_LIBCPP_CXX03_LANG)
    680 
    681 _LIBCPP_END_NAMESPACE_STD
    682 
    683 #endif  // _LIBCPP_SCOPED_ALLOCATOR
    684