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