libstdc++
|
00001 // Uses-allocator Construction -*- C++ -*- 00002 00003 // Copyright (C) 2010-2017 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, _Alloc, _Args...>::value, 00087 __uses_alloc1<_Alloc>, 00088 __uses_alloc2<_Alloc>>::type 00089 { 00090 static_assert(__or_< 00091 is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>, 00092 is_constructible<_Tp, _Args..., _Alloc>>::value, "construction with" 00093 " an allocator must be possible if uses_allocator is true"); 00094 }; 00095 00096 template<typename _Tp, typename _Alloc, typename... _Args> 00097 struct __uses_alloc<false, _Tp, _Alloc, _Args...> 00098 : __uses_alloc0 { }; 00099 00100 template<typename _Tp, typename _Alloc, typename... _Args> 00101 using __uses_alloc_t = 00102 __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>; 00103 00104 template<typename _Tp, typename _Alloc, typename... _Args> 00105 inline __uses_alloc_t<_Tp, _Alloc, _Args...> 00106 __use_alloc(const _Alloc& __a) 00107 { 00108 __uses_alloc_t<_Tp, _Alloc, _Args...> __ret; 00109 __ret._M_a = std::__addressof(__a); 00110 return __ret; 00111 } 00112 00113 template<typename _Tp, typename _Alloc, typename... _Args> 00114 void 00115 __use_alloc(const _Alloc&&) = delete; 00116 00117 #if __cplusplus > 201402L 00118 template <typename _Tp, typename _Alloc> 00119 inline constexpr bool uses_allocator_v = 00120 uses_allocator<_Tp, _Alloc>::value; 00121 #endif // C++17 00122 00123 template<template<typename...> class _Predicate, 00124 typename _Tp, typename _Alloc, typename... _Args> 00125 struct __is_uses_allocator_predicate 00126 : conditional<uses_allocator<_Tp, _Alloc>::value, 00127 __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>, 00128 _Predicate<_Tp, _Args..., _Alloc>>, 00129 _Predicate<_Tp, _Args...>>::type { }; 00130 00131 template<typename _Tp, typename _Alloc, typename... _Args> 00132 struct __is_uses_allocator_constructible 00133 : __is_uses_allocator_predicate<is_constructible, _Tp, _Alloc, _Args...> 00134 { }; 00135 00136 #if __cplusplus >= 201402L 00137 template<typename _Tp, typename _Alloc, typename... _Args> 00138 _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v = 00139 __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; 00140 #endif // C++14 00141 00142 template<typename _Tp, typename _Alloc, typename... _Args> 00143 struct __is_nothrow_uses_allocator_constructible 00144 : __is_uses_allocator_predicate<is_nothrow_constructible, 00145 _Tp, _Alloc, _Args...> 00146 { }; 00147 00148 00149 #if __cplusplus >= 201402L 00150 template<typename _Tp, typename _Alloc, typename... _Args> 00151 _GLIBCXX17_INLINE constexpr bool 00152 __is_nothrow_uses_allocator_constructible_v = 00153 __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; 00154 #endif // C++14 00155 00156 template<typename _Tp, typename... _Args> 00157 void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr, 00158 _Args&&... __args) 00159 { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); } 00160 00161 template<typename _Tp, typename _Alloc, typename... _Args> 00162 void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr, 00163 _Args&&... __args) 00164 { 00165 ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a, 00166 std::forward<_Args>(__args)...); 00167 } 00168 00169 template<typename _Tp, typename _Alloc, typename... _Args> 00170 void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr, 00171 _Args&&... __args) 00172 { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); } 00173 00174 template<typename _Tp, typename _Alloc, typename... _Args> 00175 void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr, 00176 _Args&&... __args) 00177 { 00178 __uses_allocator_construct_impl(__use_alloc<_Tp, _Alloc, _Args...>(__a), 00179 __ptr, std::forward<_Args>(__args)...); 00180 } 00181 00182 _GLIBCXX_END_NAMESPACE_VERSION 00183 } // namespace std 00184 00185 #endif 00186 #endif