1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | #ifndef _SCOPED_ALLOCATOR |
30 | #define _SCOPED_ALLOCATOR 1 |
31 | |
32 | #pragma GCC system_header |
33 | |
34 | #if __cplusplus < 201103L |
35 | # include <bits/c++0x_warning.h> |
36 | #else |
37 | |
38 | #include <utility> |
39 | #include <tuple> |
40 | #include <bits/alloc_traits.h> |
41 | |
42 | namespace std _GLIBCXX_VISIBILITY(default) |
43 | { |
44 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | template<typename _Alloc> |
52 | using __outer_allocator_t |
53 | = decltype(std::declval<_Alloc>().outer_allocator()); |
54 | |
55 | template<typename _Alloc, typename = void> |
56 | struct __outermost_type |
57 | { |
58 | using type = _Alloc; |
59 | static type& _S_outermost(_Alloc& __a) { return __a; } |
60 | }; |
61 | |
62 | template<typename _Alloc> |
63 | struct __outermost_type<_Alloc, __void_t<__outer_allocator_t<_Alloc>>> |
64 | : __outermost_type< |
65 | typename remove_reference<__outer_allocator_t<_Alloc>>::type |
66 | > |
67 | { |
68 | using __base = __outermost_type< |
69 | typename remove_reference<__outer_allocator_t<_Alloc>>::type |
70 | >; |
71 | |
72 | static typename __base::type& |
73 | _S_outermost(_Alloc& __a) |
74 | { return __base::_S_outermost(__a.outer_allocator()); } |
75 | }; |
76 | |
77 | template<typename _Alloc> |
78 | inline typename __outermost_type<_Alloc>::type& |
79 | __outermost(_Alloc& __a) |
80 | { return __outermost_type<_Alloc>::_S_outermost(__a); } |
81 | |
82 | template<typename _OuterAlloc, typename... _InnerAllocs> |
83 | class scoped_allocator_adaptor; |
84 | |
85 | template<typename...> |
86 | struct __inner_type_impl; |
87 | |
88 | template<typename _Outer> |
89 | struct __inner_type_impl<_Outer> |
90 | { |
91 | typedef scoped_allocator_adaptor<_Outer> __type; |
92 | |
93 | __inner_type_impl() = default; |
94 | __inner_type_impl(const __inner_type_impl&) = default; |
95 | __inner_type_impl(__inner_type_impl&&) = default; |
96 | __inner_type_impl& operator=(const __inner_type_impl&) = default; |
97 | __inner_type_impl& operator=(__inner_type_impl&&) = default; |
98 | |
99 | template<typename _Alloc> |
100 | __inner_type_impl(const __inner_type_impl<_Alloc>& __other) |
101 | { } |
102 | |
103 | template<typename _Alloc> |
104 | __inner_type_impl(__inner_type_impl<_Alloc>&& __other) |
105 | { } |
106 | |
107 | __type& |
108 | _M_get(__type* __p) noexcept { return *__p; } |
109 | |
110 | const __type& |
111 | _M_get(const __type* __p) const noexcept { return *__p; } |
112 | |
113 | tuple<> |
114 | _M_tie() const noexcept { return tuple<>(); } |
115 | |
116 | bool |
117 | operator==(const __inner_type_impl&) const noexcept |
118 | { return true; } |
119 | }; |
120 | |
121 | template<typename _Outer, typename _InnerHead, typename... _InnerTail> |
122 | struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...> |
123 | { |
124 | typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type; |
125 | |
126 | __inner_type_impl() = default; |
127 | __inner_type_impl(const __inner_type_impl&) = default; |
128 | __inner_type_impl(__inner_type_impl&&) = default; |
129 | __inner_type_impl& operator=(const __inner_type_impl&) = default; |
130 | __inner_type_impl& operator=(__inner_type_impl&&) = default; |
131 | |
132 | template<typename... _Allocs> |
133 | __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) |
134 | : _M_inner(__other._M_inner) { } |
135 | |
136 | template<typename... _Allocs> |
137 | __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) |
138 | : _M_inner(std::move(__other._M_inner)) { } |
139 | |
140 | template<typename... _Args> |
141 | explicit |
142 | __inner_type_impl(_Args&&... __args) |
143 | : _M_inner(std::forward<_Args>(__args)...) { } |
144 | |
145 | __type& |
146 | _M_get(void*) noexcept { return _M_inner; } |
147 | |
148 | const __type& |
149 | _M_get(const void*) const noexcept { return _M_inner; } |
150 | |
151 | tuple<const _InnerHead&, const _InnerTail&...> |
152 | _M_tie() const noexcept |
153 | { return _M_inner._M_tie(); } |
154 | |
155 | bool |
156 | operator==(const __inner_type_impl& __other) const noexcept |
157 | { return _M_inner == __other._M_inner; } |
158 | |
159 | private: |
160 | template<typename...> friend class __inner_type_impl; |
161 | template<typename, typename...> friend class scoped_allocator_adaptor; |
162 | |
163 | __type _M_inner; |
164 | }; |
165 | |
166 | |
167 | template<typename _OuterAlloc, typename... _InnerAllocs> |
168 | class scoped_allocator_adaptor |
169 | : public _OuterAlloc |
170 | { |
171 | typedef allocator_traits<_OuterAlloc> __traits; |
172 | |
173 | typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type; |
174 | __inner_type _M_inner; |
175 | |
176 | template<typename _Outer, typename... _Inner> |
177 | friend class scoped_allocator_adaptor; |
178 | |
179 | template<typename...> |
180 | friend class __inner_type_impl; |
181 | |
182 | tuple<const _OuterAlloc&, const _InnerAllocs&...> |
183 | _M_tie() const noexcept |
184 | { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); } |
185 | |
186 | template<typename _Alloc> |
187 | using __outermost_alloc_traits |
188 | = allocator_traits<typename __outermost_type<_Alloc>::type>; |
189 | |
190 | template<typename _Tp, typename... _Args> |
191 | void |
192 | _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) |
193 | { |
194 | typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; |
195 | _O_traits::construct(__outermost(*this), __p, |
196 | std::forward<_Args>(__args)...); |
197 | } |
198 | |
199 | typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_; |
200 | typedef __uses_alloc2<typename __inner_type::__type> __uses_alloc2_; |
201 | |
202 | template<typename _Tp, typename... _Args> |
203 | void |
204 | _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args) |
205 | { |
206 | typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; |
207 | _O_traits::construct(__outermost(*this), __p, |
208 | allocator_arg, inner_allocator(), |
209 | std::forward<_Args>(__args)...); |
210 | } |
211 | |
212 | template<typename _Tp, typename... _Args> |
213 | void |
214 | _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args) |
215 | { |
216 | typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; |
217 | _O_traits::construct(__outermost(*this), __p, |
218 | std::forward<_Args>(__args)..., |
219 | inner_allocator()); |
220 | } |
221 | |
222 | template<typename _Alloc> |
223 | static _Alloc |
224 | _S_select_on_copy(const _Alloc& __a) |
225 | { |
226 | typedef allocator_traits<_Alloc> __a_traits; |
227 | return __a_traits::select_on_container_copy_construction(__a); |
228 | } |
229 | |
230 | template<std::size_t... _Indices> |
231 | scoped_allocator_adaptor(tuple<const _OuterAlloc&, |
232 | const _InnerAllocs&...> __refs, |
233 | _Index_tuple<_Indices...>) |
234 | : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))), |
235 | _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...) |
236 | { } |
237 | |
238 | |
239 | template<typename _Alloc> |
240 | using _Constructible = typename enable_if< |
241 | is_constructible<_OuterAlloc, _Alloc>::value |
242 | >::type; |
243 | |
244 | public: |
245 | typedef _OuterAlloc outer_allocator_type; |
246 | typedef typename __inner_type::__type inner_allocator_type; |
247 | |
248 | typedef typename __traits::value_type value_type; |
249 | typedef typename __traits::size_type size_type; |
250 | typedef typename __traits::difference_type difference_type; |
251 | typedef typename __traits::pointer pointer; |
252 | typedef typename __traits::const_pointer const_pointer; |
253 | typedef typename __traits::void_pointer void_pointer; |
254 | typedef typename __traits::const_void_pointer const_void_pointer; |
255 | |
256 | typedef typename __or_< |
257 | typename __traits::propagate_on_container_copy_assignment, |
258 | typename allocator_traits<_InnerAllocs>:: |
259 | propagate_on_container_copy_assignment...>::type |
260 | propagate_on_container_copy_assignment; |
261 | |
262 | typedef typename __or_< |
263 | typename __traits::propagate_on_container_move_assignment, |
264 | typename allocator_traits<_InnerAllocs>:: |
265 | propagate_on_container_move_assignment...>::type |
266 | propagate_on_container_move_assignment; |
267 | |
268 | typedef typename __or_< |
269 | typename __traits::propagate_on_container_swap, |
270 | typename allocator_traits<_InnerAllocs>:: |
271 | propagate_on_container_swap...>::type |
272 | propagate_on_container_swap; |
273 | |
274 | typedef typename __and_< |
275 | typename __traits::is_always_equal, |
276 | typename allocator_traits<_InnerAllocs>::is_always_equal...>::type |
277 | is_always_equal; |
278 | |
279 | template <class _Tp> |
280 | struct rebind |
281 | { |
282 | typedef scoped_allocator_adaptor< |
283 | typename __traits::template rebind_alloc<_Tp>, |
284 | _InnerAllocs...> other; |
285 | }; |
286 | |
287 | scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { } |
288 | |
289 | template<typename _Outer2, typename = _Constructible<_Outer2>> |
290 | scoped_allocator_adaptor(_Outer2&& __outer, |
291 | const _InnerAllocs&... __inner) |
292 | : _OuterAlloc(std::forward<_Outer2>(__outer)), |
293 | _M_inner(__inner...) |
294 | { } |
295 | |
296 | scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) |
297 | : _OuterAlloc(__other.outer_allocator()), |
298 | _M_inner(__other._M_inner) |
299 | { } |
300 | |
301 | scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) |
302 | : _OuterAlloc(std::move(__other.outer_allocator())), |
303 | _M_inner(std::move(__other._M_inner)) |
304 | { } |
305 | |
306 | template<typename _Outer2, typename = _Constructible<const _Outer2&>> |
307 | scoped_allocator_adaptor( |
308 | const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other) |
309 | : _OuterAlloc(__other.outer_allocator()), |
310 | _M_inner(__other._M_inner) |
311 | { } |
312 | |
313 | template<typename _Outer2, typename = _Constructible<_Outer2>> |
314 | scoped_allocator_adaptor( |
315 | scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) |
316 | : _OuterAlloc(std::move(__other.outer_allocator())), |
317 | _M_inner(std::move(__other._M_inner)) |
318 | { } |
319 | |
320 | scoped_allocator_adaptor& |
321 | operator=(const scoped_allocator_adaptor&) = default; |
322 | |
323 | scoped_allocator_adaptor& |
324 | operator=(scoped_allocator_adaptor&&) = default; |
325 | |
326 | inner_allocator_type& inner_allocator() noexcept |
327 | { return _M_inner._M_get(this); } |
328 | |
329 | const inner_allocator_type& inner_allocator() const noexcept |
330 | { return _M_inner._M_get(this); } |
331 | |
332 | outer_allocator_type& outer_allocator() noexcept |
333 | { return static_cast<_OuterAlloc&>(*this); } |
334 | |
335 | const outer_allocator_type& outer_allocator() const noexcept |
336 | { return static_cast<const _OuterAlloc&>(*this); } |
337 | |
338 | pointer allocate(size_type __n) |
339 | { return __traits::allocate(outer_allocator(), __n); } |
340 | |
341 | pointer allocate(size_type __n, const_void_pointer __hint) |
342 | { return __traits::allocate(outer_allocator(), __n, __hint); } |
343 | |
344 | void deallocate(pointer __p, size_type __n) |
345 | { return __traits::deallocate(outer_allocator(), __p, __n); } |
346 | |
347 | size_type max_size() const |
348 | { return __traits::max_size(outer_allocator()); } |
349 | |
350 | template<typename _Tp, typename... _Args> |
351 | void construct(_Tp* __p, _Args&&... __args) |
352 | { |
353 | auto& __inner = inner_allocator(); |
354 | auto __use_tag |
355 | = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner); |
356 | _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); |
357 | } |
358 | |
359 | template<typename _T1, typename _T2, typename... _Args1, |
360 | typename... _Args2> |
361 | void |
362 | construct(pair<_T1, _T2>* __p, piecewise_construct_t, |
363 | tuple<_Args1...> __x, tuple<_Args2...> __y) |
364 | { |
365 | |
366 | |
367 | auto& __inner = inner_allocator(); |
368 | auto __x_use_tag |
369 | = __use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); |
370 | auto __y_use_tag |
371 | = __use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); |
372 | typename _Build_index_tuple<sizeof...(_Args1)>::__type __x_indices; |
373 | typename _Build_index_tuple<sizeof...(_Args2)>::__type __y_indices; |
374 | typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; |
375 | _O_traits::construct(__outermost(*this), __p, piecewise_construct, |
376 | _M_construct_p(__x_use_tag, __x_indices, __x), |
377 | _M_construct_p(__y_use_tag, __y_indices, __y)); |
378 | } |
379 | |
380 | template<typename _T1, typename _T2> |
381 | void |
382 | construct(pair<_T1, _T2>* __p) |
383 | { construct(__p, piecewise_construct, tuple<>(), tuple<>()); } |
384 | |
385 | template<typename _T1, typename _T2, typename _Up, typename _Vp> |
386 | void |
387 | construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) |
388 | { |
389 | construct(__p, piecewise_construct, |
390 | std::forward_as_tuple(std::forward<_Up>(__u)), |
391 | std::forward_as_tuple(std::forward<_Vp>(__v))); |
392 | } |
393 | |
394 | template<typename _T1, typename _T2, typename _Up, typename _Vp> |
395 | void |
396 | construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) |
397 | { |
398 | construct(__p, piecewise_construct, |
399 | std::forward_as_tuple(__x.first), |
400 | std::forward_as_tuple(__x.second)); |
401 | } |
402 | |
403 | template<typename _T1, typename _T2, typename _Up, typename _Vp> |
404 | void |
405 | construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) |
406 | { |
407 | construct(__p, piecewise_construct, |
408 | std::forward_as_tuple(std::forward<_Up>(__x.first)), |
409 | std::forward_as_tuple(std::forward<_Vp>(__x.second))); |
410 | } |
411 | |
412 | template<typename _Tp> |
413 | void destroy(_Tp* __p) |
414 | { |
415 | typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; |
416 | _O_traits::destroy(__outermost(*this), __p); |
417 | } |
418 | |
419 | scoped_allocator_adaptor |
420 | select_on_container_copy_construction() const |
421 | { |
422 | typedef typename _Build_index_tuple<sizeof...(_InnerAllocs)>::__type |
423 | _Indices; |
424 | return scoped_allocator_adaptor(_M_tie(), _Indices()); |
425 | } |
426 | |
427 | template <typename _OutA1, typename _OutA2, typename... _InA> |
428 | friend bool |
429 | operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, |
430 | const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; |
431 | |
432 | private: |
433 | template<typename _Ind, typename... _Args> |
434 | tuple<_Args&&...> |
435 | _M_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) |
436 | { return std::move(__t); } |
437 | |
438 | template<size_t... _Ind, typename... _Args> |
439 | tuple<allocator_arg_t, inner_allocator_type&, _Args&&...> |
440 | _M_construct_p(__uses_alloc1_, _Index_tuple<_Ind...>, |
441 | tuple<_Args...>& __t) |
442 | { |
443 | return { allocator_arg, inner_allocator(), |
444 | std::get<_Ind>(std::move(__t))... |
445 | }; |
446 | } |
447 | |
448 | template<size_t... _Ind, typename... _Args> |
449 | tuple<_Args&&..., inner_allocator_type&> |
450 | _M_construct_p(__uses_alloc2_, _Index_tuple<_Ind...>, |
451 | tuple<_Args...>& __t) |
452 | { |
453 | return { std::get<_Ind>(std::move(__t))..., inner_allocator() }; |
454 | } |
455 | }; |
456 | |
457 | template <typename _OutA1, typename _OutA2, typename... _InA> |
458 | inline bool |
459 | operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, |
460 | const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept |
461 | { |
462 | return __a.outer_allocator() == __b.outer_allocator() |
463 | && __a._M_inner == __b._M_inner; |
464 | } |
465 | |
466 | template <typename _OutA1, typename _OutA2, typename... _InA> |
467 | inline bool |
468 | operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, |
469 | const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept |
470 | { return !(__a == __b); } |
471 | |
472 | |
473 | |
474 | _GLIBCXX_END_NAMESPACE_VERSION |
475 | } |
476 | |
477 | #endif |
478 | |
479 | #endif |
480 | |