blob: c9544b81f08ff59cea2ef570006ec7a272fa0d2e [file] [log] [blame]
Howard Hinnante92c3d72010-08-19 18:39:17 +00001// -*- C++ -*-
2//===-------------------------- scoped_allocator --------------------------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_SCOPED_ALLOCATOR
12#define _LIBCPP_SCOPED_ALLOCATOR
13
14/*
15 scoped_allocator synopsis
16
17namespace std
18{
19
20template <class OuterAlloc, class... InnerAllocs>
21class scoped_allocator_adaptor : public OuterAlloc
22{
23 typedef allocator_traits<OuterAlloc> OuterTraits; // exposition only
Howard Hinnant324bb032010-08-22 00:02:43 +000024 scoped_allocator_adaptor<InnerAllocs...> inner; // exposition only
Howard Hinnante92c3d72010-08-19 18:39:17 +000025public:
26
27 typedef OuterAlloc outer_allocator_type;
28 typedef see below inner_allocator_type;
29
30 typedef typename OuterTraits::value_type value_type;
31 typedef typename OuterTraits::size_type size_type;
32 typedef typename OuterTraits::difference_type difference_type;
33 typedef typename OuterTraits::pointer pointer;
34 typedef typename OuterTraits::const_pointer const_pointer;
35 typedef typename OuterTraits::void_pointer void_pointer;
36 typedef typename OuterTraits::const_void_pointer const_void_pointer;
37
38 typedef see below propagate_on_container_copy_assignment;
39 typedef see below propagate_on_container_move_assignment;
40 typedef see below propagate_on_container_swap;
41
42 template <class Tp>
43 struct rebind
44 {
45 typedef scoped_allocator_adaptor<
46 OuterTraits::template rebind_alloc<Tp>, InnerAllocs...> other;
47 };
48
49 scoped_allocator_adaptor();
50 template <class OuterA2>
51 scoped_allocator_adaptor(OuterA2&& outerAlloc,
52 const InnerAllocs&... innerAllocs);
53 scoped_allocator_adaptor(const scoped_allocator_adaptor& other);
54 template <class OuterA2>
55 scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other);
56 template <class OuterA2>
57 scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other);
58
59 ~scoped_allocator_adaptor();
60
61 inner_allocator_type& inner_allocator();
62 const inner_allocator_type& inner_allocator() const;
63
64 outer_allocator_type& outer_allocator();
65 const outer_allocator_type& outer_allocator() const;
66
67 pointer allocate(size_type n);
68 pointer allocate(size_type n, const_void_pointer hint);
69 void deallocate(pointer p, size_type n);
70
71 size_type max_size() const;
72 template <class T, class... Args> void construct(T* p, Args&& args);
73 template <class T1, class T2, class... Args1, class... Args2>
74 void construct(pair<T1, T2>* p, piecewise_construct t, tuple<Args1...> x,
75 tuple<Args2...> y);
76 template <class T1, class T2>
77 void construct(pair<T1, T2>* p);
78 template <class T1, class T2, class U, class V>
79 void construct(pair<T1, T2>* p, U&& x, V&& y);
80 template <class T1, class T2, class U, class V>
81 void construct(pair<T1, T2>* p, const pair<U, V>& x);
82 template <class T1, class T2, class U, class V>
83 void construct(pair<T1, T2>* p, pair<U, V>&& x);
84 template <class T> void destroy(T* p);
85
86 scoped_allocator_adaptor select_on_container_copy_construction() const;
87};
88
89template <class OuterA1, class OuterA2, class... InnerAllocs>
90 bool
91 operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
92 const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b);
93
94template <class OuterA1, class OuterA2, class... InnerAllocs>
95 bool
96 operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
97 const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b);
98
99} // std
100
101*/
102
103#include <__config>
104#include <memory>
105
106#pragma GCC system_header
107
108_LIBCPP_BEGIN_NAMESPACE_STD
109
Howard Hinnant73d21a42010-09-04 23:28:19 +0000110#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_ADVANCED_SFINAE)
Howard Hinnante92c3d72010-08-19 18:39:17 +0000111
112// scoped_allocator_adaptor
113
114template <class ..._Allocs>
115class scoped_allocator_adaptor;
116
117template <class ..._Allocs> struct __get_poc_copy_assignment;
118
119template <class _A0>
120struct __get_poc_copy_assignment<_A0>
121{
122 static const bool value = allocator_traits<_A0>::
123 propagate_on_container_copy_assignment::value;
124};
125
126template <class _A0, class ..._Allocs>
127struct __get_poc_copy_assignment<_A0, _Allocs...>
128{
129 static const bool value =
130 allocator_traits<_A0>::propagate_on_container_copy_assignment::value ||
131 __get_poc_copy_assignment<_Allocs...>::value;
132};
133
134template <class ..._Allocs> struct __get_poc_move_assignment;
135
136template <class _A0>
137struct __get_poc_move_assignment<_A0>
138{
139 static const bool value = allocator_traits<_A0>::
140 propagate_on_container_move_assignment::value;
141};
142
143template <class _A0, class ..._Allocs>
144struct __get_poc_move_assignment<_A0, _Allocs...>
145{
146 static const bool value =
147 allocator_traits<_A0>::propagate_on_container_move_assignment::value ||
148 __get_poc_move_assignment<_Allocs...>::value;
149};
150
151template <class ..._Allocs> struct __get_poc_swap;
152
153template <class _A0>
154struct __get_poc_swap<_A0>
155{
156 static const bool value = allocator_traits<_A0>::
157 propagate_on_container_swap::value;
158};
159
160template <class _A0, class ..._Allocs>
161struct __get_poc_swap<_A0, _Allocs...>
162{
163 static const bool value =
164 allocator_traits<_A0>::propagate_on_container_swap::value ||
165 __get_poc_swap<_Allocs...>::value;
166};
167
168template <class ..._Allocs>
169class __scoped_allocator_storage;
170
171template <class _OuterAlloc, class... _InnerAllocs>
172class __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...>
173 : public _OuterAlloc
174{
175 typedef _OuterAlloc outer_allocator_type;
176protected:
177 typedef scoped_allocator_adaptor<_InnerAllocs...> inner_allocator_type;
178
179private:
180 inner_allocator_type __inner_;
181
182protected:
Howard Hinnant324bb032010-08-22 00:02:43 +0000183
Howard Hinnante92c3d72010-08-19 18:39:17 +0000184 __scoped_allocator_storage() {}
185
186 template <class _OuterA2,
187 class = typename enable_if<
188 is_constructible<outer_allocator_type, _OuterA2>::value
189 >::type>
190 __scoped_allocator_storage(_OuterA2&& __outerAlloc,
191 const _InnerAllocs& ...__innerAllocs)
192 : outer_allocator_type(_STD::forward<_OuterA2>(__outerAlloc)),
193 __inner_(__innerAllocs...) {}
194
195 template <class _OuterA2,
196 class = typename enable_if<
197 is_constructible<outer_allocator_type, const _OuterA2&>::value
198 >::type>
199 __scoped_allocator_storage(
200 const __scoped_allocator_storage<_OuterA2, _InnerAllocs...>& __other)
201 : outer_allocator_type(__other.outer_allocator()),
202 __inner_(__other.inner_allocator()) {}
203
204 template <class _OuterA2,
205 class = typename enable_if<
206 is_constructible<outer_allocator_type, _OuterA2>::value
207 >::type>
208 __scoped_allocator_storage(
209 __scoped_allocator_storage<_OuterA2, _InnerAllocs...>&& __other)
210 : outer_allocator_type(_STD::move(__other.outer_allocator())),
211 __inner_(_STD::move(__other.inner_allocator())) {}
212
213 template <class _OuterA2,
214 class = typename enable_if<
215 is_constructible<outer_allocator_type, _OuterA2>::value
216 >::type>
217 __scoped_allocator_storage(_OuterA2&& __o,
218 const inner_allocator_type& __i)
219 : outer_allocator_type(_STD::forward<_OuterA2>(__o)),
220 __inner_(__i)
221 {
222 }
223
224 inner_allocator_type& inner_allocator() {return __inner_;}
225 const inner_allocator_type& inner_allocator() const {return __inner_;}
226
227 outer_allocator_type& outer_allocator()
228 {return static_cast<outer_allocator_type&>(*this);}
229 const outer_allocator_type& outer_allocator() const
230 {return static_cast<const outer_allocator_type&>(*this);}
231
232 scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>
233 select_on_container_copy_construction() const
234 {
235 return scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>
236 (
237 allocator_traits<outer_allocator_type>::
238 select_on_container_copy_construction(outer_allocator()),
239 allocator_traits<inner_allocator_type>::
240 select_on_container_copy_construction(inner_allocator())
241 );
242 }
243
244 template <class...> friend class __scoped_allocator_storage;
245};
246
247template <class _OuterAlloc>
248class __scoped_allocator_storage<_OuterAlloc>
249 : public _OuterAlloc
250{
251 typedef _OuterAlloc outer_allocator_type;
252protected:
253 typedef scoped_allocator_adaptor<_OuterAlloc> inner_allocator_type;
254
255 __scoped_allocator_storage() {}
256
257 template <class _OuterA2,
258 class = typename enable_if<
259 is_constructible<outer_allocator_type, _OuterA2>::value
260 >::type>
261 __scoped_allocator_storage(_OuterA2&& __outerAlloc)
262 : outer_allocator_type(_STD::forward<_OuterA2>(__outerAlloc)) {}
263
264 template <class _OuterA2,
265 class = typename enable_if<
266 is_constructible<outer_allocator_type, const _OuterA2&>::value
267 >::type>
268 __scoped_allocator_storage(
269 const __scoped_allocator_storage<_OuterA2>& __other)
270 : outer_allocator_type(__other.outer_allocator()) {}
271
272 template <class _OuterA2,
273 class = typename enable_if<
274 is_constructible<outer_allocator_type, _OuterA2>::value
275 >::type>
276 __scoped_allocator_storage(
277 __scoped_allocator_storage<_OuterA2>&& __other)
278 : outer_allocator_type(_STD::move(__other.outer_allocator())) {}
279
280 inner_allocator_type& inner_allocator()
281 {return static_cast<inner_allocator_type&>(*this);}
282 const inner_allocator_type& inner_allocator() const
283 {return static_cast<const inner_allocator_type&>(*this);}
284
285 outer_allocator_type& outer_allocator()
286 {return static_cast<outer_allocator_type&>(*this);}
287 const outer_allocator_type& outer_allocator() const
288 {return static_cast<const outer_allocator_type&>(*this);}
289
290 scoped_allocator_adaptor<outer_allocator_type>
291 select_on_container_copy_construction() const
292 {return scoped_allocator_adaptor<outer_allocator_type>(
293 allocator_traits<outer_allocator_type>::
294 select_on_container_copy_construction(outer_allocator())
295 );}
296
297 __scoped_allocator_storage(const outer_allocator_type& __o,
298 const inner_allocator_type& __i);
299
300 template <class...> friend class __scoped_allocator_storage;
301};
302
303// __outermost
304
305template <class _Alloc>
306decltype(declval<_Alloc>().outer_allocator(), true_type())
307__has_outer_allocator_test(_Alloc&& __a);
308
309template <class _Alloc>
310false_type
311__has_outer_allocator_test(const volatile _Alloc& __a);
312
313template <class _Alloc>
314struct __has_outer_allocator
315 : public common_type
316 <
317 decltype(__has_outer_allocator_test(declval<_Alloc&>()))
318 >::type
319{
320};
321
322template <class _Alloc, bool = __has_outer_allocator<_Alloc>::value>
323struct __outermost
324{
325 typedef _Alloc type;
326 type& operator()(type& __a) const {return __a;}
327};
328
329template <class _Alloc>
330struct __outermost<_Alloc, true>
331{
332 typedef typename remove_reference
333 <
334 decltype(_STD::declval<_Alloc>().outer_allocator())
335 >::type _OuterAlloc;
336 typedef typename __outermost<_OuterAlloc>::type type;
337 type& operator()(_Alloc& __a) const
338 {return __outermost<_OuterAlloc>()(__a.outer_allocator());}
339};
340
341template <class _OuterAlloc, class... _InnerAllocs>
342class scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>
343 : public __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...>
344{
345 typedef __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> base;
346 typedef allocator_traits<_OuterAlloc> _OuterTraits;
347public:
348 typedef _OuterAlloc outer_allocator_type;
349 typedef typename base::inner_allocator_type inner_allocator_type;
350 typedef typename _OuterTraits::size_type size_type;
351 typedef typename _OuterTraits::difference_type difference_type;
352 typedef typename _OuterTraits::pointer pointer;
353 typedef typename _OuterTraits::const_pointer const_pointer;
354 typedef typename _OuterTraits::void_pointer void_pointer;
355 typedef typename _OuterTraits::const_void_pointer const_void_pointer;
356
357 typedef integral_constant
358 <
359 bool,
360 __get_poc_copy_assignment<outer_allocator_type,
361 _InnerAllocs...>::value
362 > propagate_on_container_copy_assignment;
363 typedef integral_constant
364 <
365 bool,
366 __get_poc_move_assignment<outer_allocator_type,
367 _InnerAllocs...>::value
368 > propagate_on_container_move_assignment;
369 typedef integral_constant
370 <
371 bool,
372 __get_poc_swap<outer_allocator_type, _InnerAllocs...>::value
373 > propagate_on_container_swap;
374
375 template <class _Tp>
376 struct rebind
377 {
378 typedef scoped_allocator_adaptor
379 <
380 typename _OuterTraits::template rebind_alloc<_Tp>, _InnerAllocs...
381 > other;
382 };
383
384 scoped_allocator_adaptor() {}
385 template <class _OuterA2,
386 class = typename enable_if<
387 is_constructible<outer_allocator_type, _OuterA2>::value
388 >::type>
389 scoped_allocator_adaptor(_OuterA2&& __outerAlloc,
390 const _InnerAllocs& ...__innerAllocs)
391 : base(_STD::forward<_OuterA2>(__outerAlloc), __innerAllocs...) {}
392 // scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) = default;
393 template <class _OuterA2,
394 class = typename enable_if<
395 is_constructible<outer_allocator_type, const _OuterA2&>::value
396 >::type>
397 scoped_allocator_adaptor(
398 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __other)
399 : base(__other) {}
400 template <class _OuterA2,
401 class = typename enable_if<
402 is_constructible<outer_allocator_type, _OuterA2>::value
403 >::type>
404 scoped_allocator_adaptor(
405 scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>&& __other)
406 : base(_STD::move(__other)) {}
407
408 // ~scoped_allocator_adaptor() = default;
409
410 inner_allocator_type& inner_allocator()
411 {return base::inner_allocator();}
412 const inner_allocator_type& inner_allocator() const
413 {return base::inner_allocator();}
414
415 outer_allocator_type& outer_allocator()
416 {return base::outer_allocator();}
417 const outer_allocator_type& outer_allocator() const
418 {return base::outer_allocator();}
419
420 pointer allocate(size_type __n)
421 {return allocator_traits<outer_allocator_type>::
422 allocate(outer_allocator(), __n);}
423 pointer allocate(size_type __n, const_void_pointer __hint)
424 {return allocator_traits<outer_allocator_type>::
425 allocate(outer_allocator(), __n, __hint);}
426
427 void deallocate(pointer __p, size_type __n)
428 {allocator_traits<outer_allocator_type>::
429 deallocate(outer_allocator(), __p, __n);}
430
431 size_type max_size() const
432 {allocator_traits<outer_allocator_type>::max_size(outer_allocator());}
433
434 template <class _Tp, class... _Args>
435 void construct(_Tp* __p, _Args&& ...__args)
436 {__construct(__uses_alloc_ctor<_Tp, inner_allocator_type, _Args...>(),
437 __p, _STD::forward<_Args>(__args)...);}
438 template <class _Tp>
439 void destroy(_Tp* __p)
440 {
441 typedef __outermost<outer_allocator_type> _OM;
442 allocator_traits<typename _OM::type>::
443 destroy(_OM()(outer_allocator()), __p);
444 }
445
446 scoped_allocator_adaptor select_on_container_copy_construction() const
447 {return base::select_on_container_copy_construction();}
448
449private:
450
451 template <class _OuterA2,
452 class = typename enable_if<
453 is_constructible<outer_allocator_type, _OuterA2>::value
454 >::type>
455 scoped_allocator_adaptor(_OuterA2&& __o,
456 const inner_allocator_type& __i)
457 : base(_STD::forward<_OuterA2>(__o), __i) {}
458
459 template <class _Tp, class... _Args>
460 void __construct(integral_constant<int, 0>, _Tp* __p, _Args&& ...__args)
461 {
462 typedef __outermost<outer_allocator_type> _OM;
463 allocator_traits<typename _OM::type>::construct
464 (
465 _OM()(outer_allocator()),
466 __p,
467 _STD::forward<_Args>(__args)...
468 );
469 }
470
471 template <class _Tp, class... _Args>
472 void __construct(integral_constant<int, 1>, _Tp* __p, _Args&& ...__args)
473 {
474 typedef __outermost<outer_allocator_type> _OM;
475 allocator_traits<typename _OM::type>::construct
476 (
477 _OM()(outer_allocator()),
478 __p,
479 allocator_arg,
480 inner_allocator(),
481 _STD::forward<_Args>(__args)...
482 );
483 }
484
485 template <class _Tp, class... _Args>
486 void __construct(integral_constant<int, 2>, _Tp* __p, _Args&& ...__args)
487 {
488 typedef __outermost<outer_allocator_type> _OM;
489 allocator_traits<typename _OM::type>::construct
490 (
491 _OM()(outer_allocator()),
492 __p,
493 _STD::forward<_Args>(__args)...,
494 inner_allocator()
495 );
496 }
497
498 template <class...> friend class __scoped_allocator_storage;
499};
500
501template <class _OuterA1, class _OuterA2>
502inline _LIBCPP_INLINE_VISIBILITY
503bool
504operator==(const scoped_allocator_adaptor<_OuterA1>& __a,
505 const scoped_allocator_adaptor<_OuterA2>& __b)
506{
507 return __a.outer_allocator() == __b.outer_allocator();
508}
509
510template <class _OuterA1, class _OuterA2, class... _InnerAllocs>
511inline _LIBCPP_INLINE_VISIBILITY
512bool
513operator==(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a,
514 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __b)
515{
516 return __a.outer_allocator() == __b.outer_allocator() &&
517 __a.inner_allocator() == __b.inner_allocator();
518}
519
520template <class _OuterA1, class _OuterA2, class... _InnerAllocs>
521inline _LIBCPP_INLINE_VISIBILITY
522bool
523operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a,
524 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __b)
525{
526 return !(__a == __b);
527}
528
Howard Hinnant73d21a42010-09-04 23:28:19 +0000529#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_ADVANCED_SFINAE)
Howard Hinnante92c3d72010-08-19 18:39:17 +0000530
531_LIBCPP_END_NAMESPACE_STD
532
533#endif // _LIBCPP_SCOPED_ALLOCATOR