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;
45 typedef scoped_allocator_adaptor<
46 OuterTraits::template rebind_alloc<Tp>, InnerAllocs...> other;
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;
60 ~scoped_allocator_adaptor();
62 inner_allocator_type& inner_allocator() noexcept;
63 const inner_allocator_type& inner_allocator() const noexcept;
65 outer_allocator_type& outer_allocator() noexcept;
66 const outer_allocator_type& outer_allocator() const noexcept;
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;
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,
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);
87 template <class T> void destroy(T* p) noexcept;
89 scoped_allocator_adaptor select_on_container_copy_construction() const noexcept;
92 template <class OuterA1, class OuterA2, class... InnerAllocs>
94 operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
95 const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
97 template <class OuterA1, class OuterA2, class... InnerAllocs>
99 operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
100 const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
109 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
110 #pragma GCC system_header
113 _LIBCPP_BEGIN_NAMESPACE_STD
115 #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_ADVANCED_SFINAE)
117 // scoped_allocator_adaptor
119 template <class ..._Allocs>
120 class scoped_allocator_adaptor;
122 template <class ..._Allocs> struct __get_poc_copy_assignment;
125 struct __get_poc_copy_assignment<_A0>
127 static const bool value = allocator_traits<_A0>::
128 propagate_on_container_copy_assignment::value;
131 template <class _A0, class ..._Allocs>
132 struct __get_poc_copy_assignment<_A0, _Allocs...>
134 static const bool value =
135 allocator_traits<_A0>::propagate_on_container_copy_assignment::value ||
136 __get_poc_copy_assignment<_Allocs...>::value;
139 template <class ..._Allocs> struct __get_poc_move_assignment;
142 struct __get_poc_move_assignment<_A0>
144 static const bool value = allocator_traits<_A0>::
145 propagate_on_container_move_assignment::value;
148 template <class _A0, class ..._Allocs>
149 struct __get_poc_move_assignment<_A0, _Allocs...>
151 static const bool value =
152 allocator_traits<_A0>::propagate_on_container_move_assignment::value ||
153 __get_poc_move_assignment<_Allocs...>::value;
156 template <class ..._Allocs> struct __get_poc_swap;
159 struct __get_poc_swap<_A0>
161 static const bool value = allocator_traits<_A0>::
162 propagate_on_container_swap::value;
165 template <class _A0, class ..._Allocs>
166 struct __get_poc_swap<_A0, _Allocs...>
168 static const bool value =
169 allocator_traits<_A0>::propagate_on_container_swap::value ||
170 __get_poc_swap<_Allocs...>::value;
173 template <class ..._Allocs>
174 class __scoped_allocator_storage;
176 template <class _OuterAlloc, class... _InnerAllocs>
177 class __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...>
180 typedef _OuterAlloc outer_allocator_type;
182 typedef scoped_allocator_adaptor<_InnerAllocs...> inner_allocator_type;
185 inner_allocator_type __inner_;
189 _LIBCPP_INLINE_VISIBILITY
190 __scoped_allocator_storage() _NOEXCEPT {}
192 template <class _OuterA2,
193 class = typename enable_if<
194 is_constructible<outer_allocator_type, _OuterA2>::value
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...) {}
202 template <class _OuterA2,
203 class = typename enable_if<
204 is_constructible<outer_allocator_type, const _OuterA2&>::value
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()) {}
212 template <class _OuterA2,
213 class = typename enable_if<
214 is_constructible<outer_allocator_type, _OuterA2>::value
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())) {}
222 template <class _OuterA2,
223 class = typename enable_if<
224 is_constructible<outer_allocator_type, _OuterA2>::value
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)),
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_;}
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);}
246 scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>
247 _LIBCPP_INLINE_VISIBILITY
248 select_on_container_copy_construction() const _NOEXCEPT
250 return scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>
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())
259 template <class...> friend class __scoped_allocator_storage;
262 template <class _OuterAlloc>
263 class __scoped_allocator_storage<_OuterAlloc>
266 typedef _OuterAlloc outer_allocator_type;
268 typedef scoped_allocator_adaptor<_OuterAlloc> inner_allocator_type;
270 _LIBCPP_INLINE_VISIBILITY
271 __scoped_allocator_storage() _NOEXCEPT {}
273 template <class _OuterA2,
274 class = typename enable_if<
275 is_constructible<outer_allocator_type, _OuterA2>::value
277 _LIBCPP_INLINE_VISIBILITY
278 __scoped_allocator_storage(_OuterA2&& __outerAlloc) _NOEXCEPT
279 : outer_allocator_type(_VSTD::forward<_OuterA2>(__outerAlloc)) {}
281 template <class _OuterA2,
282 class = typename enable_if<
283 is_constructible<outer_allocator_type, const _OuterA2&>::value
285 _LIBCPP_INLINE_VISIBILITY
286 __scoped_allocator_storage(
287 const __scoped_allocator_storage<_OuterA2>& __other) _NOEXCEPT
288 : outer_allocator_type(__other.outer_allocator()) {}
290 template <class _OuterA2,
291 class = typename enable_if<
292 is_constructible<outer_allocator_type, _OuterA2>::value
294 _LIBCPP_INLINE_VISIBILITY
295 __scoped_allocator_storage(
296 __scoped_allocator_storage<_OuterA2>&& __other) _NOEXCEPT
297 : outer_allocator_type(_VSTD::move(__other.outer_allocator())) {}
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);}
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);}
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())
321 __scoped_allocator_storage(const outer_allocator_type& __o,
322 const inner_allocator_type& __i) _NOEXCEPT;
324 template <class...> friend class __scoped_allocator_storage;
329 template <class _Alloc>
330 decltype(declval<_Alloc>().outer_allocator(), true_type())
331 __has_outer_allocator_test(_Alloc&& __a);
333 template <class _Alloc>
335 __has_outer_allocator_test(const volatile _Alloc& __a);
337 template <class _Alloc>
338 struct __has_outer_allocator
341 decltype(__has_outer_allocator_test(declval<_Alloc&>()))
346 template <class _Alloc, bool = __has_outer_allocator<_Alloc>::value>
350 _LIBCPP_INLINE_VISIBILITY
351 type& operator()(type& __a) const _NOEXCEPT {return __a;}
354 template <class _Alloc>
355 struct __outermost<_Alloc, true>
357 typedef typename remove_reference
359 decltype(_VSTD::declval<_Alloc>().outer_allocator())
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());}
367 template <class _OuterAlloc, class... _InnerAllocs>
368 class _LIBCPP_VISIBLE scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>
369 : public __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...>
371 typedef __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> base;
372 typedef allocator_traits<_OuterAlloc> _OuterTraits;
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;
383 typedef integral_constant
386 __get_poc_copy_assignment<outer_allocator_type,
387 _InnerAllocs...>::value
388 > propagate_on_container_copy_assignment;
389 typedef integral_constant
392 __get_poc_move_assignment<outer_allocator_type,
393 _InnerAllocs...>::value
394 > propagate_on_container_move_assignment;
395 typedef integral_constant
398 __get_poc_swap<outer_allocator_type, _InnerAllocs...>::value
399 > propagate_on_container_swap;
404 typedef scoped_allocator_adaptor
406 typename _OuterTraits::template rebind_alloc<_Tp>, _InnerAllocs...
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
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
425 _LIBCPP_INLINE_VISIBILITY
426 scoped_allocator_adaptor(
427 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT
429 template <class _OuterA2,
430 class = typename enable_if<
431 is_constructible<outer_allocator_type, _OuterA2>::value
433 _LIBCPP_INLINE_VISIBILITY
434 scoped_allocator_adaptor(
435 scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT
436 : base(_VSTD::move(__other)) {}
438 // ~scoped_allocator_adaptor() = default;
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();}
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();}
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);}
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);}
468 _LIBCPP_INLINE_VISIBILITY
469 size_type max_size() const
470 {return allocator_traits<outer_allocator_type>::max_size(outer_allocator());}
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)...);}
478 _LIBCPP_INLINE_VISIBILITY
479 void destroy(_Tp* __p)
481 typedef __outermost<outer_allocator_type> _OM;
482 allocator_traits<typename _OM::type>::
483 destroy(_OM()(outer_allocator()), __p);
486 _LIBCPP_INLINE_VISIBILITY
487 scoped_allocator_adaptor select_on_container_copy_construction() const _NOEXCEPT
488 {return base::select_on_container_copy_construction();}
492 template <class _OuterA2,
493 class = typename enable_if<
494 is_constructible<outer_allocator_type, _OuterA2>::value
496 _LIBCPP_INLINE_VISIBILITY
497 scoped_allocator_adaptor(_OuterA2&& __o,
498 const inner_allocator_type& __i) _NOEXCEPT
499 : base(_VSTD::forward<_OuterA2>(__o), __i) {}
501 template <class _Tp, class... _Args>
502 _LIBCPP_INLINE_VISIBILITY
503 void __construct(integral_constant<int, 0>, _Tp* __p, _Args&& ...__args)
505 typedef __outermost<outer_allocator_type> _OM;
506 allocator_traits<typename _OM::type>::construct
508 _OM()(outer_allocator()),
510 _VSTD::forward<_Args>(__args)...
514 template <class _Tp, class... _Args>
515 _LIBCPP_INLINE_VISIBILITY
516 void __construct(integral_constant<int, 1>, _Tp* __p, _Args&& ...__args)
518 typedef __outermost<outer_allocator_type> _OM;
519 allocator_traits<typename _OM::type>::construct
521 _OM()(outer_allocator()),
525 _VSTD::forward<_Args>(__args)...
529 template <class _Tp, class... _Args>
530 _LIBCPP_INLINE_VISIBILITY
531 void __construct(integral_constant<int, 2>, _Tp* __p, _Args&& ...__args)
533 typedef __outermost<outer_allocator_type> _OM;
534 allocator_traits<typename _OM::type>::construct
536 _OM()(outer_allocator()),
538 _VSTD::forward<_Args>(__args)...,
543 template <class...> friend class __scoped_allocator_storage;
546 template <class _OuterA1, class _OuterA2>
547 inline _LIBCPP_INLINE_VISIBILITY
549 operator==(const scoped_allocator_adaptor<_OuterA1>& __a,
550 const scoped_allocator_adaptor<_OuterA2>& __b) _NOEXCEPT
552 return __a.outer_allocator() == __b.outer_allocator();
555 template <class _OuterA1, class _OuterA2, class _InnerA0, class... _InnerAllocs>
556 inline _LIBCPP_INLINE_VISIBILITY
558 operator==(const scoped_allocator_adaptor<_OuterA1, _InnerA0, _InnerAllocs...>& __a,
559 const scoped_allocator_adaptor<_OuterA2, _InnerA0, _InnerAllocs...>& __b) _NOEXCEPT
561 return __a.outer_allocator() == __b.outer_allocator() &&
562 __a.inner_allocator() == __b.inner_allocator();
565 template <class _OuterA1, class _OuterA2, class... _InnerAllocs>
566 inline _LIBCPP_INLINE_VISIBILITY
568 operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a,
569 const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __b) _NOEXCEPT
571 return !(__a == __b);
574 #endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_ADVANCED_SFINAE)
576 _LIBCPP_END_NAMESPACE_STD
578 #endif // _LIBCPP_SCOPED_ALLOCATOR