2 //===-------------------------- scoped_allocator --------------------------===//
4 // The LLVM Compiler Infrastructure
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 #ifndef _LIBCPP_SCOPED_ALLOCATOR
12 #define _LIBCPP_SCOPED_ALLOCATOR
15 scoped_allocator synopsis
20 template <class OuterAlloc, class... InnerAllocs>
21 class scoped_allocator_adaptor : public OuterAlloc
23 typedef allocator_traits<OuterAlloc> OuterTraits; // exposition only
24 scoped_allocator_adaptor<InnerAllocs...> inner; // exposition only
27 typedef OuterAlloc outer_allocator_type;
28 typedef see below inner_allocator_type;
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;
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 typedef see below is_always_equal;
46 typedef scoped_allocator_adaptor<
47 OuterTraits::template rebind_alloc<Tp>, InnerAllocs...> other;
50 scoped_allocator_adaptor();
51 template <class OuterA2>
52 scoped_allocator_adaptor(OuterA2&& outerAlloc,
53 const InnerAllocs&... innerAllocs) noexcept;
54 scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
55 scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
56 template <class OuterA2>
57 scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
58 template <class OuterA2>
59 scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
61 scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default;
62 scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default;
63 ~scoped_allocator_adaptor();
65 inner_allocator_type& inner_allocator() noexcept;
66 const inner_allocator_type& inner_allocator() const noexcept;
68 outer_allocator_type& outer_allocator() noexcept;
69 const outer_allocator_type& outer_allocator() const noexcept;
71 pointer allocate(size_type n);
72 pointer allocate(size_type n, const_void_pointer hint);
73 void deallocate(pointer p, size_type n) noexcept;
75 size_type max_size() const;
76 template <class T, class... Args> void construct(T* p, Args&& args);
77 template <class T1, class T2, class... Args1, class... Args2>
78 void construct(pair<T1, T2>* p, piecewise_construct t, tuple<Args1...> x,
80 template <class T1, class T2>
81 void construct(pair<T1, T2>* p);
82 template <class T1, class T2, class U, class V>
83 void construct(pair<T1, T2>* p, U&& x, V&& y);
84 template <class T1, class T2, class U, class V>
85 void construct(pair<T1, T2>* p, const pair<U, V>& x);
86 template <class T1, class T2, class U, class V>
87 void construct(pair<T1, T2>* p, pair<U, V>&& x);
88 template <class T> void destroy(T* p);
90 template <class T> void destroy(T* p) noexcept;
92 scoped_allocator_adaptor select_on_container_copy_construction() const noexcept;
95 template <class OuterA1, class OuterA2, class... InnerAllocs>
97 operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
98 const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
100 template <class OuterA1, class OuterA2, class... InnerAllocs>
102 operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
103 const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
112 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
113 #pragma GCC system_header
116 _LIBCPP_BEGIN_NAMESPACE_STD
118 #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_ADVANCED_SFINAE)
120 // scoped_allocator_adaptor
122 template <class ..._Allocs>
123 class scoped_allocator_adaptor;
125 template <class ..._Allocs> struct __get_poc_copy_assignment;
128 struct __get_poc_copy_assignment<_A0>
130 static const bool value = allocator_traits<_A0>::
131 propagate_on_container_copy_assignment::value;
134 template <class _A0, class ..._Allocs>
135 struct __get_poc_copy_assignment<_A0, _Allocs...>
137 static const bool value =
138 allocator_traits<_A0>::propagate_on_container_copy_assignment::value ||
139 __get_poc_copy_assignment<_Allocs...>::value;
142 template <class ..._Allocs> struct __get_poc_move_assignment;
145 struct __get_poc_move_assignment<_A0>
147 static const bool value = allocator_traits<_A0>::
148 propagate_on_container_move_assignment::value;
151 template <class _A0, class ..._Allocs>
152 struct __get_poc_move_assignment<_A0, _Allocs...>
154 static const bool value =
155 allocator_traits<_A0>::propagate_on_container_move_assignment::value ||
156 __get_poc_move_assignment<_Allocs...>::value;
159 template <class ..._Allocs> struct __get_poc_swap;
162 struct __get_poc_swap<_A0>
164 static const bool value = allocator_traits<_A0>::
165 propagate_on_container_swap::value;
168 template <class _A0, class ..._Allocs>
169 struct __get_poc_swap<_A0, _Allocs...>
171 static const bool value =
172 allocator_traits<_A0>::propagate_on_container_swap::value ||
173 __get_poc_swap<_Allocs...>::value;
176 template <class ..._Allocs> struct __get_is_always_equal;
179 struct __get_is_always_equal<_A0>
181 static const bool value = allocator_traits<_A0>::is_always_equal::value;
184 template <class _A0, class ..._Allocs>
185 struct __get_is_always_equal<_A0, _Allocs...>
187 static const bool value =
188 allocator_traits<_A0>::is_always_equal::value &&
189 __get_is_always_equal<_Allocs...>::value;
192 template <class ..._Allocs>
193 class __scoped_allocator_storage;
195 template <class _OuterAlloc, class... _InnerAllocs>
196 class __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...>
199 typedef _OuterAlloc outer_allocator_type;
201 typedef scoped_allocator_adaptor<_InnerAllocs...> inner_allocator_type;
204 inner_allocator_type __inner_;
208 _LIBCPP_INLINE_VISIBILITY
209 __scoped_allocator_storage() _NOEXCEPT {}
211 template <class _OuterA2,
212 class = typename enable_if<
213 is_constructible<outer_allocator_type, _OuterA2>::value
215 _LIBCPP_INLINE_VISIBILITY
216 __scoped_allocator_storage(_OuterA2&& __outerAlloc,
217 const _InnerAllocs& ...__innerAllocs) _NOEXCEPT
218 : outer_allocator_type(_VSTD::forward<_OuterA2>(__outerAlloc)),
219 __inner_(__innerAllocs...) {}
221 template <class _OuterA2,
222 class = typename enable_if<
223 is_constructible<outer_allocator_type, const _OuterA2&>::value
225 _LIBCPP_INLINE_VISIBILITY
226 __scoped_allocator_storage(
227 const __scoped_allocator_storage<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT
228 : outer_allocator_type(__other.outer_allocator()),
229 __inner_(__other.inner_allocator()) {}
231 template <class _OuterA2,
232 class = typename enable_if<
233 is_constructible<outer_allocator_type, _OuterA2>::value
235 _LIBCPP_INLINE_VISIBILITY
236 __scoped_allocator_storage(
237 __scoped_allocator_storage<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT
238 : outer_allocator_type(_VSTD::move(__other.outer_allocator())),
239 __inner_(_VSTD::move(__other.inner_allocator())) {}
241 template <class _OuterA2,
242 class = typename enable_if<
243 is_constructible<outer_allocator_type, _OuterA2>::value
245 _LIBCPP_INLINE_VISIBILITY
246 __scoped_allocator_storage(_OuterA2&& __o,
247 const inner_allocator_type& __i) _NOEXCEPT
248 : outer_allocator_type(_VSTD::forward<_OuterA2>(__o)),
253 _LIBCPP_INLINE_VISIBILITY
254 inner_allocator_type& inner_allocator() _NOEXCEPT {return __inner_;}
255 _LIBCPP_INLINE_VISIBILITY
256 const inner_allocator_type& inner_allocator() const _NOEXCEPT {return __inner_;}
258 _LIBCPP_INLINE_VISIBILITY
259 outer_allocator_type& outer_allocator() _NOEXCEPT
260 {return static_cast<outer_allocator_type&>(*this);}
261 _LIBCPP_INLINE_VISIBILITY
262 const outer_allocator_type& outer_allocator() const _NOEXCEPT
263 {return static_cast<const outer_allocator_type&>(*this);}
265 scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>
266 _LIBCPP_INLINE_VISIBILITY
267 select_on_container_copy_construction() const _NOEXCEPT
269 return scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>
271 allocator_traits<outer_allocator_type>::
272 select_on_container_copy_construction(outer_allocator()),
273 allocator_traits<inner_allocator_type>::
274 select_on_container_copy_construction(inner_allocator())
278 template <class...> friend class __scoped_allocator_storage;
281 template <class _OuterAlloc>
282 class __scoped_allocator_storage<_OuterAlloc>
285 typedef _OuterAlloc outer_allocator_type;
287 typedef scoped_allocator_adaptor<_OuterAlloc> inner_allocator_type;
289 _LIBCPP_INLINE_VISIBILITY
290 __scoped_allocator_storage() _NOEXCEPT {}
292 template <class _OuterA2,
293 class = typename enable_if<
294 is_constructible<outer_allocator_type, _OuterA2>::value
296 _LIBCPP_INLINE_VISIBILITY
297 __scoped_allocator_storage(_OuterA2&& __outerAlloc) _NOEXCEPT
298 : outer_allocator_type(_VSTD::forward<_OuterA2>(__outerAlloc)) {}
300 template <class _OuterA2,
301 class = typename enable_if<
302 is_constructible<outer_allocator_type, const _OuterA2&>::value
304 _LIBCPP_INLINE_VISIBILITY
305 __scoped_allocator_storage(
306 const __scoped_allocator_storage<_OuterA2>& __other) _NOEXCEPT
307 : outer_allocator_type(__other.outer_allocator()) {}
309 template <class _OuterA2,
310 class = typename enable_if<
311 is_constructible<outer_allocator_type, _OuterA2>::value
313 _LIBCPP_INLINE_VISIBILITY
314 __scoped_allocator_storage(
315 __scoped_allocator_storage<_OuterA2>&& __other) _NOEXCEPT
316 : outer_allocator_type(_VSTD::move(__other.outer_allocator())) {}
318 _LIBCPP_INLINE_VISIBILITY
319 inner_allocator_type& inner_allocator() _NOEXCEPT
320 {return static_cast<inner_allocator_type&>(*this);}
321 _LIBCPP_INLINE_VISIBILITY
322 const inner_allocator_type& inner_allocator() const _NOEXCEPT
323 {return static_cast<const inner_allocator_type&>(*this);}
325 _LIBCPP_INLINE_VISIBILITY
326 outer_allocator_type& outer_allocator() _NOEXCEPT
327 {return static_cast<outer_allocator_type&>(*this);}
328 _LIBCPP_INLINE_VISIBILITY
329 const outer_allocator_type& outer_allocator() const _NOEXCEPT
330 {return static_cast<const outer_allocator_type&>(*this);}
332 _LIBCPP_INLINE_VISIBILITY
333 scoped_allocator_adaptor<outer_allocator_type>
334 select_on_container_copy_construction() const _NOEXCEPT
335 {return scoped_allocator_adaptor<outer_allocator_type>(
336 allocator_traits<outer_allocator_type>::
337 select_on_container_copy_construction(outer_allocator())
340 __scoped_allocator_storage(const outer_allocator_type& __o,
341 const inner_allocator_type& __i) _NOEXCEPT;
343 template <class...> friend class __scoped_allocator_storage;
348 template <class _Alloc>
349 decltype(declval<_Alloc>().outer_allocator(), true_type())
350 __has_outer_allocator_test(_Alloc&& __a);
352 template <class _Alloc>
354 __has_outer_allocator_test(const volatile _Alloc& __a);
356 template <class _Alloc>
357 struct __has_outer_allocator
360 decltype(__has_outer_allocator_test(declval<_Alloc&>()))
365 template <class _Alloc, bool = __has_outer_allocator<_Alloc>::value>
369 _LIBCPP_INLINE_VISIBILITY
370 type& operator()(type& __a) const _NOEXCEPT {return __a;}
373 template <class _Alloc>
374 struct __outermost<_Alloc, true>
376 typedef typename remove_reference
378 decltype(_VSTD::declval<_Alloc>().outer_allocator())
380 typedef typename __outermost<_OuterAlloc>::type type;
381 _LIBCPP_INLINE_VISIBILITY
382 type& operator()(_Alloc& __a) const _NOEXCEPT
383 {return __outermost<_OuterAlloc>()(__a.outer_allocator());}
386 template <class _OuterAlloc, class... _InnerAllocs>
387 class _LIBCPP_TYPE_VIS_ONLY scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>
388 : public __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...>
390 typedef __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> base;
391 typedef allocator_traits<_OuterAlloc> _OuterTraits;
393 typedef _OuterAlloc outer_allocator_type;
394 typedef typename base::inner_allocator_type inner_allocator_type;
395 typedef typename _OuterTraits::size_type size_type;
396 typedef typename _OuterTraits::difference_type difference_type;
397 typedef typename _OuterTraits::pointer pointer;
398 typedef typename _OuterTraits::const_pointer const_pointer;
399 typedef typename _OuterTraits::void_pointer void_pointer;
400 typedef typename _OuterTraits::const_void_pointer const_void_pointer;
402 typedef integral_constant
405 __get_poc_copy_assignment<outer_allocator_type,
406 _InnerAllocs...>::value
407 > propagate_on_container_copy_assignment;
408 typedef integral_constant
411 __get_poc_move_assignment<outer_allocator_type,
412 _InnerAllocs...>::value
413 > propagate_on_container_move_assignment;
414 typedef integral_constant
417 __get_poc_swap<outer_allocator_type, _InnerAllocs...>::value
418 > propagate_on_container_swap;
419 typedef integral_constant
422 __get_is_always_equal<outer_allocator_type, _InnerAllocs...>::value
428 typedef scoped_allocator_adaptor
430 typename _OuterTraits::template rebind_alloc<_Tp>, _InnerAllocs...
434 _LIBCPP_INLINE_VISIBILITY
435 scoped_allocator_adaptor() _NOEXCEPT {}
436 template <class _OuterA2,
437 class = typename enable_if<
438 is_constructible<outer_allocator_type, _OuterA2>::value
440 _LIBCPP_INLINE_VISIBILITY
441 scoped_allocator_adaptor(_OuterA2&& __outerAlloc,
442 const _InnerAllocs& ...__innerAllocs) _NOEXCEPT
443 : base(_VSTD::forward<_OuterA2>(__outerAlloc), __innerAllocs...) {}
444 // scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) = default;
445 template <class _OuterA2,
446 class = typename enable_if<
447 is_constructible<outer_allocator_type, const _OuterA2&>::value
449 _LIBCPP_INLINE_VISIBILITY
450 scoped_allocator_adaptor(
451 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT
453 template <class _OuterA2,
454 class = typename enable_if<
455 is_constructible<outer_allocator_type, _OuterA2>::value
457 _LIBCPP_INLINE_VISIBILITY
458 scoped_allocator_adaptor(
459 scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT
460 : base(_VSTD::move(__other)) {}
462 // scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default;
463 // scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default;
464 // ~scoped_allocator_adaptor() = default;
466 _LIBCPP_INLINE_VISIBILITY
467 inner_allocator_type& inner_allocator() _NOEXCEPT
468 {return base::inner_allocator();}
469 _LIBCPP_INLINE_VISIBILITY
470 const inner_allocator_type& inner_allocator() const _NOEXCEPT
471 {return base::inner_allocator();}
473 _LIBCPP_INLINE_VISIBILITY
474 outer_allocator_type& outer_allocator() _NOEXCEPT
475 {return base::outer_allocator();}
476 _LIBCPP_INLINE_VISIBILITY
477 const outer_allocator_type& outer_allocator() const _NOEXCEPT
478 {return base::outer_allocator();}
480 _LIBCPP_INLINE_VISIBILITY
481 pointer allocate(size_type __n)
482 {return allocator_traits<outer_allocator_type>::
483 allocate(outer_allocator(), __n);}
484 _LIBCPP_INLINE_VISIBILITY
485 pointer allocate(size_type __n, const_void_pointer __hint)
486 {return allocator_traits<outer_allocator_type>::
487 allocate(outer_allocator(), __n, __hint);}
489 _LIBCPP_INLINE_VISIBILITY
490 void deallocate(pointer __p, size_type __n) _NOEXCEPT
491 {allocator_traits<outer_allocator_type>::
492 deallocate(outer_allocator(), __p, __n);}
494 _LIBCPP_INLINE_VISIBILITY
495 size_type max_size() const
496 {return allocator_traits<outer_allocator_type>::max_size(outer_allocator());}
498 template <class _Tp, class... _Args>
499 _LIBCPP_INLINE_VISIBILITY
500 void construct(_Tp* __p, _Args&& ...__args)
501 {__construct(__uses_alloc_ctor<_Tp, inner_allocator_type, _Args...>(),
502 __p, _VSTD::forward<_Args>(__args)...);}
504 _LIBCPP_INLINE_VISIBILITY
505 void destroy(_Tp* __p)
507 typedef __outermost<outer_allocator_type> _OM;
508 allocator_traits<typename _OM::type>::
509 destroy(_OM()(outer_allocator()), __p);
512 _LIBCPP_INLINE_VISIBILITY
513 scoped_allocator_adaptor select_on_container_copy_construction() const _NOEXCEPT
514 {return base::select_on_container_copy_construction();}
518 template <class _OuterA2,
519 class = typename enable_if<
520 is_constructible<outer_allocator_type, _OuterA2>::value
522 _LIBCPP_INLINE_VISIBILITY
523 scoped_allocator_adaptor(_OuterA2&& __o,
524 const inner_allocator_type& __i) _NOEXCEPT
525 : base(_VSTD::forward<_OuterA2>(__o), __i) {}
527 template <class _Tp, class... _Args>
528 _LIBCPP_INLINE_VISIBILITY
529 void __construct(integral_constant<int, 0>, _Tp* __p, _Args&& ...__args)
531 typedef __outermost<outer_allocator_type> _OM;
532 allocator_traits<typename _OM::type>::construct
534 _OM()(outer_allocator()),
536 _VSTD::forward<_Args>(__args)...
540 template <class _Tp, class... _Args>
541 _LIBCPP_INLINE_VISIBILITY
542 void __construct(integral_constant<int, 1>, _Tp* __p, _Args&& ...__args)
544 typedef __outermost<outer_allocator_type> _OM;
545 allocator_traits<typename _OM::type>::construct
547 _OM()(outer_allocator()),
551 _VSTD::forward<_Args>(__args)...
555 template <class _Tp, class... _Args>
556 _LIBCPP_INLINE_VISIBILITY
557 void __construct(integral_constant<int, 2>, _Tp* __p, _Args&& ...__args)
559 typedef __outermost<outer_allocator_type> _OM;
560 allocator_traits<typename _OM::type>::construct
562 _OM()(outer_allocator()),
564 _VSTD::forward<_Args>(__args)...,
569 template <class...> friend class __scoped_allocator_storage;
572 template <class _OuterA1, class _OuterA2>
573 inline _LIBCPP_INLINE_VISIBILITY
575 operator==(const scoped_allocator_adaptor<_OuterA1>& __a,
576 const scoped_allocator_adaptor<_OuterA2>& __b) _NOEXCEPT
578 return __a.outer_allocator() == __b.outer_allocator();
581 template <class _OuterA1, class _OuterA2, class _InnerA0, class... _InnerAllocs>
582 inline _LIBCPP_INLINE_VISIBILITY
584 operator==(const scoped_allocator_adaptor<_OuterA1, _InnerA0, _InnerAllocs...>& __a,
585 const scoped_allocator_adaptor<_OuterA2, _InnerA0, _InnerAllocs...>& __b) _NOEXCEPT
587 return __a.outer_allocator() == __b.outer_allocator() &&
588 __a.inner_allocator() == __b.inner_allocator();
591 template <class _OuterA1, class _OuterA2, class... _InnerAllocs>
592 inline _LIBCPP_INLINE_VISIBILITY
594 operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a,
595 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __b) _NOEXCEPT
597 return !(__a == __b);
600 #endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_ADVANCED_SFINAE)
602 _LIBCPP_END_NAMESPACE_STD
604 #endif // _LIBCPP_SCOPED_ALLOCATOR