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