Home | History | Annotate | Line # | Download | only in bits
      1 // Uses-allocator Construction -*- C++ -*-
      2 
      3 // Copyright (C) 2010-2024 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file include/bits/uses_allocator_args.h
     26  *  This is an internal header file, included by other library headers.
     27  *  Do not attempt to use it directly. @headername{memory}
     28  */
     29 
     30 #ifndef _USES_ALLOCATOR_H
     31 #define _USES_ALLOCATOR_H 1
     32 
     33 #if __cplusplus < 201103L
     34 # include <bits/c++0x_warning.h>
     35 #else
     36 
     37 #include <type_traits>
     38 #include <bits/move.h>
     39 
     40 namespace std _GLIBCXX_VISIBILITY(default)
     41 {
     42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     43 /// @cond undocumented
     44 
     45   // This is used for std::experimental::erased_type from Library Fundamentals.
     46   struct __erased_type { };
     47 
     48   // This also supports the "type-erased allocator" protocol from the
     49   // Library Fundamentals TS, where allocator_type is erased_type.
     50   // The second condition will always be false for types not using the TS.
     51   template<typename _Alloc, typename _Tp>
     52     using __is_erased_or_convertible
     53       = __or_<is_convertible<_Alloc, _Tp>, is_same<_Tp, __erased_type>>;
     54 
     55   /// [allocator.tag]
     56   struct allocator_arg_t { explicit allocator_arg_t() = default; };
     57 
     58   _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg =
     59     allocator_arg_t();
     60 
     61   template<typename _Tp, typename _Alloc, typename = __void_t<>>
     62     struct __uses_allocator_helper
     63     : false_type { };
     64 
     65   template<typename _Tp, typename _Alloc>
     66     struct __uses_allocator_helper<_Tp, _Alloc,
     67 				   __void_t<typename _Tp::allocator_type>>
     68     : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type
     69     { };
     70 
     71   /// [allocator.uses.trait]
     72   template<typename _Tp, typename _Alloc>
     73     struct uses_allocator
     74     : __uses_allocator_helper<_Tp, _Alloc>::type
     75     { };
     76 
     77   struct __uses_alloc_base { };
     78 
     79   struct __uses_alloc0 : __uses_alloc_base
     80   {
     81     struct _Sink { void _GLIBCXX20_CONSTEXPR operator=(const void*) { } } _M_a;
     82   };
     83 
     84   template<typename _Alloc>
     85     struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; };
     86 
     87   template<typename _Alloc>
     88     struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; };
     89 
     90   template<bool, typename _Tp, typename _Alloc, typename... _Args>
     91     struct __uses_alloc;
     92 
     93   template<typename _Tp, typename _Alloc, typename... _Args>
     94     struct __uses_alloc<true, _Tp, _Alloc, _Args...>
     95     : __conditional_t<
     96         is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value,
     97         __uses_alloc1<_Alloc>,
     98        	__uses_alloc2<_Alloc>>
     99     {
    100       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    101       // 2586. Wrong value category used in scoped_allocator_adaptor::construct
    102       static_assert(__or_<
    103 	  is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>,
    104 	  is_constructible<_Tp, _Args..., const _Alloc&>>::value,
    105 	  "construction with an allocator must be possible"
    106 	  " if uses_allocator is true");
    107     };
    108 
    109   template<typename _Tp, typename _Alloc, typename... _Args>
    110     struct __uses_alloc<false, _Tp, _Alloc, _Args...>
    111     : __uses_alloc0 { };
    112 
    113   template<typename _Tp, typename _Alloc, typename... _Args>
    114     using __uses_alloc_t =
    115       __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>;
    116 
    117   template<typename _Tp, typename _Alloc, typename... _Args>
    118     _GLIBCXX20_CONSTEXPR
    119     inline __uses_alloc_t<_Tp, _Alloc, _Args...>
    120     __use_alloc(const _Alloc& __a)
    121     {
    122       __uses_alloc_t<_Tp, _Alloc, _Args...> __ret;
    123       __ret._M_a = std::__addressof(__a);
    124       return __ret;
    125     }
    126 
    127   template<typename _Tp, typename _Alloc, typename... _Args>
    128     void
    129     __use_alloc(const _Alloc&&) = delete;
    130 
    131 #if __cplusplus > 201402L
    132   template <typename _Tp, typename _Alloc>
    133     inline constexpr bool uses_allocator_v =
    134       uses_allocator<_Tp, _Alloc>::value;
    135 #endif // C++17
    136 
    137   template<template<typename...> class _Predicate,
    138 	   typename _Tp, typename _Alloc, typename... _Args>
    139     struct __is_uses_allocator_predicate
    140     : __conditional_t<uses_allocator<_Tp, _Alloc>::value,
    141       __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>,
    142 	    _Predicate<_Tp, _Args..., _Alloc>>,
    143       _Predicate<_Tp, _Args...>> { };
    144 
    145   template<typename _Tp, typename _Alloc, typename... _Args>
    146     struct __is_uses_allocator_constructible
    147     : __is_uses_allocator_predicate<is_constructible, _Tp, _Alloc, _Args...>
    148     { };
    149 
    150 #if __cplusplus >= 201402L
    151   template<typename _Tp, typename _Alloc, typename... _Args>
    152     _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v =
    153       __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
    154 #endif // C++14
    155 
    156   template<typename _Tp, typename _Alloc, typename... _Args>
    157     struct __is_nothrow_uses_allocator_constructible
    158     : __is_uses_allocator_predicate<is_nothrow_constructible,
    159 				    _Tp, _Alloc, _Args...>
    160     { };
    161 
    162 
    163 #if __cplusplus >= 201402L
    164   template<typename _Tp, typename _Alloc, typename... _Args>
    165     _GLIBCXX17_INLINE constexpr bool
    166     __is_nothrow_uses_allocator_constructible_v =
    167       __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
    168 #endif // C++14
    169 
    170   template<typename _Tp, typename... _Args>
    171     void __uses_allocator_construct_impl(__uses_alloc0, _Tp* __ptr,
    172 					 _Args&&... __args)
    173     { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); }
    174 
    175   template<typename _Tp, typename _Alloc, typename... _Args>
    176     void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr,
    177 					 _Args&&... __args)
    178     {
    179       ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a,
    180 			       std::forward<_Args>(__args)...);
    181     }
    182 
    183   template<typename _Tp, typename _Alloc, typename... _Args>
    184     void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr,
    185 					 _Args&&... __args)
    186     { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); }
    187 
    188   template<typename _Tp, typename _Alloc, typename... _Args>
    189     void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr,
    190 				    _Args&&... __args)
    191     {
    192       std::__uses_allocator_construct_impl(
    193 	  std::__use_alloc<_Tp, _Alloc, _Args...>(__a), __ptr,
    194 	  std::forward<_Args>(__args)...);
    195     }
    196 
    197 /// @endcond
    198 _GLIBCXX_END_NAMESPACE_VERSION
    199 } // namespace std
    200 
    201 #endif
    202 #endif
    203