1// Uses-allocator Construction -*- C++ -*- 
2 
3// Copyright (C) 2010-2021 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#ifndef _USES_ALLOCATOR_H 
26#define _USES_ALLOCATOR_H 1 
27 
28#if __cplusplus < 201103L 
29# include <bits/c++0x_warning.h> 
30#else 
31 
32#include <type_traits> 
33#include <bits/move.h> 
34 
35namespace std _GLIBCXX_VISIBILITY(default
36
37_GLIBCXX_BEGIN_NAMESPACE_VERSION 
38/// @cond undocumented 
39 
40 // This is used for std::experimental::erased_type from Library Fundamentals. 
41 struct __erased_type { }; 
42 
43 // This also supports the "type-erased allocator" protocol from the 
44 // Library Fundamentals TS, where allocator_type is erased_type. 
45 // The second condition will always be false for types not using the TS. 
46 template<typename _Alloc, typename _Tp> 
47 using __is_erased_or_convertible 
48 = __or_<is_convertible<_Alloc, _Tp>, is_same<_Tp, __erased_type>>; 
49 
50 /// [allocator.tag] 
51 struct allocator_arg_t { explicit allocator_arg_t() = default; }; 
52 
53 _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg
54 allocator_arg_t(); 
55 
56 template<typename _Tp, typename _Alloc, typename = __void_t<>> 
57 struct __uses_allocator_helper 
58 : false_type { }; 
59 
60 template<typename _Tp, typename _Alloc> 
61 struct __uses_allocator_helper<_Tp, _Alloc, 
62 __void_t<typename _Tp::allocator_type>> 
63 : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type 
64 { }; 
65 
66 /// [allocator.uses.trait] 
67 template<typename _Tp, typename _Alloc> 
68 struct uses_allocator 
69 : __uses_allocator_helper<_Tp, _Alloc>::type 
70 { }; 
71 
72 struct __uses_alloc_base { }; 
73 
74 struct __uses_alloc0 : __uses_alloc_base 
75
76 struct _Sink { void _GLIBCXX20_CONSTEXPR operator=(const void*) { } } _M_a
77 }; 
78 
79 template<typename _Alloc> 
80 struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; }; 
81 
82 template<typename _Alloc> 
83 struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; }; 
84 
85 template<bool, typename _Tp, typename _Alloc, typename... _Args> 
86 struct __uses_alloc
87 
88 template<typename _Tp, typename _Alloc, typename... _Args> 
89 struct __uses_alloc<true, _Tp, _Alloc, _Args...> 
90 : conditional
91 is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value, 
92 __uses_alloc1<_Alloc>, 
93 __uses_alloc2<_Alloc>>::type 
94
95 // _GLIBCXX_RESOLVE_LIB_DEFECTS 
96 // 2586. Wrong value category used in scoped_allocator_adaptor::construct 
97 static_assert(__or_
98 is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>, 
99 is_constructible<_Tp, _Args..., const _Alloc&>>::value, 
100 "construction with an allocator must be possible" 
101 " if uses_allocator is true"); 
102 }; 
103 
104 template<typename _Tp, typename _Alloc, typename... _Args> 
105 struct __uses_alloc<false, _Tp, _Alloc, _Args...> 
106 : __uses_alloc0 { }; 
107 
108 template<typename _Tp, typename _Alloc, typename... _Args> 
109 using __uses_alloc_t
110 __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>; 
111 
112 template<typename _Tp, typename _Alloc, typename... _Args> 
113 _GLIBCXX20_CONSTEXPR 
114 inline __uses_alloc_t<_Tp, _Alloc, _Args...> 
115 __use_alloc(const _Alloc& __a
116
117 __uses_alloc_t<_Tp, _Alloc, _Args...> __ret
118 __ret._M_a = std::__addressof(__a); 
119 return __ret
120
121 
122 template<typename _Tp, typename _Alloc, typename... _Args> 
123 void 
124 __use_alloc(const _Alloc&&) = delete
125 
126#if __cplusplus > 201402L 
127 template <typename _Tp, typename _Alloc> 
128 inline constexpr bool uses_allocator_v
129 uses_allocator<_Tp, _Alloc>::value; 
130#endif // C++17 
131 
132 template<template<typename...> class _Predicate, 
133 typename _Tp, typename _Alloc, typename... _Args> 
134 struct __is_uses_allocator_predicate 
135 : conditional<uses_allocator<_Tp, _Alloc>::value, 
136 __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>, 
137 _Predicate<_Tp, _Args..., _Alloc>>, 
138 _Predicate<_Tp, _Args...>>::type { }; 
139 
140 template<typename _Tp, typename _Alloc, typename... _Args> 
141 struct __is_uses_allocator_constructible 
142 : __is_uses_allocator_predicate<is_constructible, _Tp, _Alloc, _Args...> 
143 { }; 
144 
145#if __cplusplus >= 201402L 
146 template<typename _Tp, typename _Alloc, typename... _Args> 
147 _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v
148 __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; 
149#endif // C++14 
150 
151 template<typename _Tp, typename _Alloc, typename... _Args> 
152 struct __is_nothrow_uses_allocator_constructible 
153 : __is_uses_allocator_predicate<is_nothrow_constructible, 
154 _Tp, _Alloc, _Args...> 
155 { }; 
156 
157 
158#if __cplusplus >= 201402L 
159 template<typename _Tp, typename _Alloc, typename... _Args> 
160 _GLIBCXX17_INLINE constexpr bool 
161 __is_nothrow_uses_allocator_constructible_v
162 __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; 
163#endif // C++14 
164 
165 template<typename _Tp, typename... _Args> 
166 void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr
167 _Args&&... __args
168 { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); } 
169 
170 template<typename _Tp, typename _Alloc, typename... _Args> 
171 void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr
172 _Args&&... __args
173
174 ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a, 
175 std::forward<_Args>(__args)...); 
176
177 
178 template<typename _Tp, typename _Alloc, typename... _Args> 
179 void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr
180 _Args&&... __args
181 { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); } 
182 
183 template<typename _Tp, typename _Alloc, typename... _Args> 
184 void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr
185 _Args&&... __args
186
187 std::__uses_allocator_construct_impl( 
188 std::__use_alloc<_Tp, _Alloc, _Args...>(__a), __ptr
189 std::forward<_Args>(__args)...); 
190
191 
192/// @endcond 
193_GLIBCXX_END_NAMESPACE_VERSION 
194} // namespace std 
195 
196#endif 
197#endif 
198