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