|
libstdc++
|
00001 // Uses-allocator Construction -*- C++ -*- 00002 00003 // Copyright (C) 2010-2018 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 #ifndef _USES_ALLOCATOR_H 00026 #define _USES_ALLOCATOR_H 1 00027 00028 #if __cplusplus < 201103L 00029 # include <bits/c++0x_warning.h> 00030 #else 00031 00032 #include <type_traits> 00033 #include <bits/move.h> 00034 00035 namespace std _GLIBCXX_VISIBILITY(default) 00036 { 00037 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00038 00039 struct __erased_type { }; 00040 00041 template<typename _Alloc, typename _Tp> 00042 using __is_erased_or_convertible 00043 = __or_<is_same<_Tp, __erased_type>, is_convertible<_Alloc, _Tp>>; 00044 00045 /// [allocator.tag] 00046 struct allocator_arg_t { explicit allocator_arg_t() = default; }; 00047 00048 _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg = 00049 allocator_arg_t(); 00050 00051 template<typename _Tp, typename _Alloc, typename = __void_t<>> 00052 struct __uses_allocator_helper 00053 : false_type { }; 00054 00055 template<typename _Tp, typename _Alloc> 00056 struct __uses_allocator_helper<_Tp, _Alloc, 00057 __void_t<typename _Tp::allocator_type>> 00058 : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type 00059 { }; 00060 00061 /// [allocator.uses.trait] 00062 template<typename _Tp, typename _Alloc> 00063 struct uses_allocator 00064 : __uses_allocator_helper<_Tp, _Alloc>::type 00065 { }; 00066 00067 struct __uses_alloc_base { }; 00068 00069 struct __uses_alloc0 : __uses_alloc_base 00070 { 00071 struct _Sink { void operator=(const void*) { } } _M_a; 00072 }; 00073 00074 template<typename _Alloc> 00075 struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; }; 00076 00077 template<typename _Alloc> 00078 struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; }; 00079 00080 template<bool, typename _Tp, typename _Alloc, typename... _Args> 00081 struct __uses_alloc; 00082 00083 template<typename _Tp, typename _Alloc, typename... _Args> 00084 struct __uses_alloc<true, _Tp, _Alloc, _Args...> 00085 : conditional< 00086 is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value, 00087 __uses_alloc1<_Alloc>, 00088 __uses_alloc2<_Alloc>>::type 00089 { 00090 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00091 // 2586. Wrong value category used in scoped_allocator_adaptor::construct 00092 static_assert(__or_< 00093 is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>, 00094 is_constructible<_Tp, _Args..., const _Alloc&>>::value, 00095 "construction with an allocator must be possible" 00096 " if uses_allocator is true"); 00097 }; 00098 00099 template<typename _Tp, typename _Alloc, typename... _Args> 00100 struct __uses_alloc<false, _Tp, _Alloc, _Args...> 00101 : __uses_alloc0 { }; 00102 00103 template<typename _Tp, typename _Alloc, typename... _Args> 00104 using __uses_alloc_t = 00105 __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>; 00106 00107 template<typename _Tp, typename _Alloc, typename... _Args> 00108 inline __uses_alloc_t<_Tp, _Alloc, _Args...> 00109 __use_alloc(const _Alloc& __a) 00110 { 00111 __uses_alloc_t<_Tp, _Alloc, _Args...> __ret; 00112 __ret._M_a = std::__addressof(__a); 00113 return __ret; 00114 } 00115 00116 template<typename _Tp, typename _Alloc, typename... _Args> 00117 void 00118 __use_alloc(const _Alloc&&) = delete; 00119 00120 #if __cplusplus > 201402L 00121 template <typename _Tp, typename _Alloc> 00122 inline constexpr bool uses_allocator_v = 00123 uses_allocator<_Tp, _Alloc>::value; 00124 #endif // C++17 00125 00126 template<template<typename...> class _Predicate, 00127 typename _Tp, typename _Alloc, typename... _Args> 00128 struct __is_uses_allocator_predicate 00129 : conditional<uses_allocator<_Tp, _Alloc>::value, 00130 __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>, 00131 _Predicate<_Tp, _Args..., _Alloc>>, 00132 _Predicate<_Tp, _Args...>>::type { }; 00133 00134 template<typename _Tp, typename _Alloc, typename... _Args> 00135 struct __is_uses_allocator_constructible 00136 : __is_uses_allocator_predicate<is_constructible, _Tp, _Alloc, _Args...> 00137 { }; 00138 00139 #if __cplusplus >= 201402L 00140 template<typename _Tp, typename _Alloc, typename... _Args> 00141 _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v = 00142 __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; 00143 #endif // C++14 00144 00145 template<typename _Tp, typename _Alloc, typename... _Args> 00146 struct __is_nothrow_uses_allocator_constructible 00147 : __is_uses_allocator_predicate<is_nothrow_constructible, 00148 _Tp, _Alloc, _Args...> 00149 { }; 00150 00151 00152 #if __cplusplus >= 201402L 00153 template<typename _Tp, typename _Alloc, typename... _Args> 00154 _GLIBCXX17_INLINE constexpr bool 00155 __is_nothrow_uses_allocator_constructible_v = 00156 __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; 00157 #endif // C++14 00158 00159 template<typename _Tp, typename... _Args> 00160 void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr, 00161 _Args&&... __args) 00162 { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); } 00163 00164 template<typename _Tp, typename _Alloc, typename... _Args> 00165 void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr, 00166 _Args&&... __args) 00167 { 00168 ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a, 00169 std::forward<_Args>(__args)...); 00170 } 00171 00172 template<typename _Tp, typename _Alloc, typename... _Args> 00173 void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr, 00174 _Args&&... __args) 00175 { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); } 00176 00177 template<typename _Tp, typename _Alloc, typename... _Args> 00178 void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr, 00179 _Args&&... __args) 00180 { 00181 __uses_allocator_construct_impl(__use_alloc<_Tp, _Alloc, _Args...>(__a), 00182 __ptr, std::forward<_Args>(__args)...); 00183 } 00184 00185 _GLIBCXX_END_NAMESPACE_VERSION 00186 } // namespace std 00187 00188 #endif 00189 #endif