1 // Allocator traits -*- C++ -*-
3 // Copyright (C) 2011-2021 Free Software Foundation, Inc.
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)
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.
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.
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/>.
25 /** @file bits/alloc_traits.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
30 #ifndef _ALLOC_TRAITS_H
31 #define _ALLOC_TRAITS_H 1
33 #include <bits/stl_construct.h>
34 #include <bits/memoryfwd.h>
35 #if __cplusplus >= 201103L
36 # include <bits/allocator.h>
37 # include <bits/ptr_traits.h>
38 # include <ext/numeric_traits.h>
41 namespace std
_GLIBCXX_VISIBILITY(default)
43 _GLIBCXX_BEGIN_NAMESPACE_VERSION
45 #if __cplusplus >= 201103L
46 #define __cpp_lib_allocator_traits_is_always_equal 201411
48 struct __allocator_traits_base
50 template<typename _Tp
, typename _Up
, typename
= void>
51 struct __rebind
: __replace_first_arg
<_Tp
, _Up
> { };
53 template<typename _Tp
, typename _Up
>
54 struct __rebind
<_Tp
, _Up
,
55 __void_t
<typename
_Tp::template rebind
<_Up
>::other
>>
56 { using type
= typename
_Tp::template rebind
<_Up
>::other
; };
59 template<typename _Tp
>
60 using __pointer
= typename
_Tp::pointer
;
61 template<typename _Tp
>
62 using __c_pointer
= typename
_Tp::const_pointer
;
63 template<typename _Tp
>
64 using __v_pointer
= typename
_Tp::void_pointer
;
65 template<typename _Tp
>
66 using __cv_pointer
= typename
_Tp::const_void_pointer
;
67 template<typename _Tp
>
68 using __pocca
= typename
_Tp::propagate_on_container_copy_assignment
;
69 template<typename _Tp
>
70 using __pocma
= typename
_Tp::propagate_on_container_move_assignment
;
71 template<typename _Tp
>
72 using __pocs
= typename
_Tp::propagate_on_container_swap
;
73 template<typename _Tp
>
74 using __equal
= typename
_Tp::is_always_equal
;
77 template<typename _Alloc
, typename _Up
>
79 = typename
__allocator_traits_base::template __rebind
<_Alloc
, _Up
>::type
;
82 * @brief Uniform interface to all allocator types.
85 template<typename _Alloc
>
86 struct allocator_traits
: __allocator_traits_base
88 /// The allocator type
89 typedef _Alloc allocator_type
;
90 /// The allocated type
91 typedef typename
_Alloc::value_type value_type
;
94 * @brief The allocator's pointer type.
96 * @c Alloc::pointer if that type exists, otherwise @c value_type*
98 using pointer
= __detected_or_t
<value_type
*, __pointer
, _Alloc
>;
101 // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
102 template<template<typename
> class _Func
, typename _Tp
, typename
= void>
105 using type
= typename pointer_traits
<pointer
>::template rebind
<_Tp
>;
108 template<template<typename
> class _Func
, typename _Tp
>
109 struct _Ptr
<_Func
, _Tp
, __void_t
<_Func
<_Alloc
>>>
111 using type
= _Func
<_Alloc
>;
114 // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
115 template<typename _A2
, typename _PtrT
, typename
= void>
117 { using type
= typename pointer_traits
<_PtrT
>::difference_type
; };
119 template<typename _A2
, typename _PtrT
>
120 struct _Diff
<_A2
, _PtrT
, __void_t
<typename
_A2::difference_type
>>
121 { using type
= typename
_A2::difference_type
; };
123 // Select _A2::size_type or make_unsigned<_DiffT>::type
124 template<typename _A2
, typename _DiffT
, typename
= void>
125 struct _Size
: make_unsigned
<_DiffT
> { };
127 template<typename _A2
, typename _DiffT
>
128 struct _Size
<_A2
, _DiffT
, __void_t
<typename
_A2::size_type
>>
129 { using type
= typename
_A2::size_type
; };
133 * @brief The allocator's const pointer type.
135 * @c Alloc::const_pointer if that type exists, otherwise
136 * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
138 using const_pointer
= typename _Ptr
<__c_pointer
, const value_type
>::type
;
141 * @brief The allocator's void pointer type.
143 * @c Alloc::void_pointer if that type exists, otherwise
144 * <tt> pointer_traits<pointer>::rebind<void> </tt>
146 using void_pointer
= typename _Ptr
<__v_pointer
, void>::type
;
149 * @brief The allocator's const void pointer type.
151 * @c Alloc::const_void_pointer if that type exists, otherwise
152 * <tt> pointer_traits<pointer>::rebind<const void> </tt>
154 using const_void_pointer
= typename _Ptr
<__cv_pointer
, const void>::type
;
157 * @brief The allocator's difference type
159 * @c Alloc::difference_type if that type exists, otherwise
160 * <tt> pointer_traits<pointer>::difference_type </tt>
162 using difference_type
= typename _Diff
<_Alloc
, pointer
>::type
;
165 * @brief The allocator's size type
167 * @c Alloc::size_type if that type exists, otherwise
168 * <tt> make_unsigned<difference_type>::type </tt>
170 using size_type
= typename _Size
<_Alloc
, difference_type
>::type
;
173 * @brief How the allocator is propagated on copy assignment
175 * @c Alloc::propagate_on_container_copy_assignment if that type exists,
176 * otherwise @c false_type
178 using propagate_on_container_copy_assignment
179 = __detected_or_t
<false_type
, __pocca
, _Alloc
>;
182 * @brief How the allocator is propagated on move assignment
184 * @c Alloc::propagate_on_container_move_assignment if that type exists,
185 * otherwise @c false_type
187 using propagate_on_container_move_assignment
188 = __detected_or_t
<false_type
, __pocma
, _Alloc
>;
191 * @brief How the allocator is propagated on swap
193 * @c Alloc::propagate_on_container_swap if that type exists,
194 * otherwise @c false_type
196 using propagate_on_container_swap
197 = __detected_or_t
<false_type
, __pocs
, _Alloc
>;
200 * @brief Whether all instances of the allocator type compare equal.
202 * @c Alloc::is_always_equal if that type exists,
203 * otherwise @c is_empty<Alloc>::type
205 using is_always_equal
206 = __detected_or_t
<typename is_empty
<_Alloc
>::type
, __equal
, _Alloc
>;
208 template<typename _Tp
>
209 using rebind_alloc
= __alloc_rebind
<_Alloc
, _Tp
>;
210 template<typename _Tp
>
211 using rebind_traits
= allocator_traits
<rebind_alloc
<_Tp
>>;
214 template<typename _Alloc2
>
215 static constexpr auto
216 _S_allocate(_Alloc2
& __a
, size_type __n
, const_void_pointer __hint
, int)
217 -> decltype(__a
.allocate(__n
, __hint
))
218 { return __a
.allocate(__n
, __hint
); }
220 template<typename _Alloc2
>
221 static constexpr pointer
222 _S_allocate(_Alloc2
& __a
, size_type __n
, const_void_pointer
, ...)
223 { return __a
.allocate(__n
); }
225 template<typename _Tp
, typename
... _Args
>
226 struct __construct_helper
228 template<typename _Alloc2
,
229 typename
= decltype(std::declval
<_Alloc2
*>()->construct(
230 std::declval
<_Tp
*>(), std::declval
<_Args
>()...))>
231 static true_type
__test(int);
234 static false_type
__test(...);
236 using type
= decltype(__test
<_Alloc
>(0));
239 template<typename _Tp
, typename
... _Args
>
240 using __has_construct
241 = typename __construct_helper
<_Tp
, _Args
...>::type
;
243 template<typename _Tp
, typename
... _Args
>
244 static _GLIBCXX14_CONSTEXPR _Require
<__has_construct
<_Tp
, _Args
...>>
245 _S_construct(_Alloc
& __a
, _Tp
* __p
, _Args
&&... __args
)
246 noexcept(noexcept(__a
.construct(__p
, std::forward
<_Args
>(__args
)...)))
247 { __a
.construct(__p
, std::forward
<_Args
>(__args
)...); }
249 template<typename _Tp
, typename
... _Args
>
250 static _GLIBCXX14_CONSTEXPR
251 _Require
<__and_
<__not_
<__has_construct
<_Tp
, _Args
...>>,
252 is_constructible
<_Tp
, _Args
...>>>
253 _S_construct(_Alloc
&, _Tp
* __p
, _Args
&&... __args
)
254 noexcept(std::is_nothrow_constructible
<_Tp
, _Args
...>::value
)
256 #if __cplusplus <= 201703L
257 ::new((void*)__p
) _Tp(std::forward
<_Args
>(__args
)...);
259 std::construct_at(__p
, std::forward
<_Args
>(__args
)...);
263 template<typename _Alloc2
, typename _Tp
>
264 static _GLIBCXX14_CONSTEXPR
auto
265 _S_destroy(_Alloc2
& __a
, _Tp
* __p
, int)
266 noexcept(noexcept(__a
.destroy(__p
)))
267 -> decltype(__a
.destroy(__p
))
268 { __a
.destroy(__p
); }
270 template<typename _Alloc2
, typename _Tp
>
271 static _GLIBCXX14_CONSTEXPR
void
272 _S_destroy(_Alloc2
&, _Tp
* __p
, ...)
273 noexcept(std::is_nothrow_destructible
<_Tp
>::value
)
274 { std::_Destroy(__p
); }
276 template<typename _Alloc2
>
277 static constexpr auto
278 _S_max_size(_Alloc2
& __a
, int)
279 -> decltype(__a
.max_size())
280 { return __a
.max_size(); }
282 template<typename _Alloc2
>
283 static constexpr size_type
284 _S_max_size(_Alloc2
&, ...)
286 // _GLIBCXX_RESOLVE_LIB_DEFECTS
287 // 2466. allocator_traits::max_size() default behavior is incorrect
288 return __gnu_cxx::__numeric_traits
<size_type
>::__max
289 / sizeof(value_type
);
292 template<typename _Alloc2
>
293 static constexpr auto
294 _S_select(_Alloc2
& __a
, int)
295 -> decltype(__a
.select_on_container_copy_construction())
296 { return __a
.select_on_container_copy_construction(); }
298 template<typename _Alloc2
>
299 static constexpr _Alloc2
300 _S_select(_Alloc2
& __a
, ...)
306 * @brief Allocate memory.
307 * @param __a An allocator.
308 * @param __n The number of objects to allocate space for.
310 * Calls @c a.allocate(n)
312 _GLIBCXX_NODISCARD
static _GLIBCXX20_CONSTEXPR pointer
313 allocate(_Alloc
& __a
, size_type __n
)
314 { return __a
.allocate(__n
); }
317 * @brief Allocate memory.
318 * @param __a An allocator.
319 * @param __n The number of objects to allocate space for.
320 * @param __hint Aid to locality.
321 * @return Memory of suitable size and alignment for @a n objects
322 * of type @c value_type
324 * Returns <tt> a.allocate(n, hint) </tt> if that expression is
325 * well-formed, otherwise returns @c a.allocate(n)
327 _GLIBCXX_NODISCARD
static _GLIBCXX20_CONSTEXPR pointer
328 allocate(_Alloc
& __a
, size_type __n
, const_void_pointer __hint
)
329 { return _S_allocate(__a
, __n
, __hint
, 0); }
332 * @brief Deallocate memory.
333 * @param __a An allocator.
334 * @param __p Pointer to the memory to deallocate.
335 * @param __n The number of objects space was allocated for.
337 * Calls <tt> a.deallocate(p, n) </tt>
339 static _GLIBCXX20_CONSTEXPR
void
340 deallocate(_Alloc
& __a
, pointer __p
, size_type __n
)
341 { __a
.deallocate(__p
, __n
); }
344 * @brief Construct an object of type `_Tp`
345 * @param __a An allocator.
346 * @param __p Pointer to memory of suitable size and alignment for Tp
347 * @param __args Constructor arguments.
349 * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
350 * if that expression is well-formed, otherwise uses placement-new
351 * to construct an object of type @a _Tp at location @a __p from the
352 * arguments @a __args...
354 template<typename _Tp
, typename
... _Args
>
355 static _GLIBCXX20_CONSTEXPR
auto
356 construct(_Alloc
& __a
, _Tp
* __p
, _Args
&&... __args
)
357 noexcept(noexcept(_S_construct(__a
, __p
,
358 std::forward
<_Args
>(__args
)...)))
359 -> decltype(_S_construct(__a
, __p
, std::forward
<_Args
>(__args
)...))
360 { _S_construct(__a
, __p
, std::forward
<_Args
>(__args
)...); }
363 * @brief Destroy an object of type @a _Tp
364 * @param __a An allocator.
365 * @param __p Pointer to the object to destroy
367 * Calls @c __a.destroy(__p) if that expression is well-formed,
368 * otherwise calls @c __p->~_Tp()
370 template<typename _Tp
>
371 static _GLIBCXX20_CONSTEXPR
void
372 destroy(_Alloc
& __a
, _Tp
* __p
)
373 noexcept(noexcept(_S_destroy(__a
, __p
, 0)))
374 { _S_destroy(__a
, __p
, 0); }
377 * @brief The maximum supported allocation size
378 * @param __a An allocator.
379 * @return @c __a.max_size() or @c numeric_limits<size_type>::max()
381 * Returns @c __a.max_size() if that expression is well-formed,
382 * otherwise returns @c numeric_limits<size_type>::max()
384 static _GLIBCXX20_CONSTEXPR size_type
385 max_size(const _Alloc
& __a
) noexcept
386 { return _S_max_size(__a
, 0); }
389 * @brief Obtain an allocator to use when copying a container.
390 * @param __rhs An allocator.
391 * @return @c __rhs.select_on_container_copy_construction() or @a __rhs
393 * Returns @c __rhs.select_on_container_copy_construction() if that
394 * expression is well-formed, otherwise returns @a __rhs
396 static _GLIBCXX20_CONSTEXPR _Alloc
397 select_on_container_copy_construction(const _Alloc
& __rhs
)
398 { return _S_select(__rhs
, 0); }
401 #if __cplusplus > 201703L
402 # define __cpp_lib_constexpr_dynamic_alloc 201907L
405 /// Partial specialization for std::allocator.
406 template<typename _Tp
>
407 struct allocator_traits
<allocator
<_Tp
>>
409 /// The allocator type
410 using allocator_type
= allocator
<_Tp
>;
412 /// The allocated type
413 using value_type
= _Tp
;
415 /// The allocator's pointer type.
416 using pointer
= _Tp
*;
418 /// The allocator's const pointer type.
419 using const_pointer
= const _Tp
*;
421 /// The allocator's void pointer type.
422 using void_pointer
= void*;
424 /// The allocator's const void pointer type.
425 using const_void_pointer
= const void*;
427 /// The allocator's difference type
428 using difference_type
= std::ptrdiff_t;
430 /// The allocator's size type
431 using size_type
= std::size_t;
433 /// How the allocator is propagated on copy assignment
434 using propagate_on_container_copy_assignment
= false_type
;
436 /// How the allocator is propagated on move assignment
437 using propagate_on_container_move_assignment
= true_type
;
439 /// How the allocator is propagated on swap
440 using propagate_on_container_swap
= false_type
;
442 /// Whether all instances of the allocator type compare equal.
443 using is_always_equal
= true_type
;
445 template<typename _Up
>
446 using rebind_alloc
= allocator
<_Up
>;
448 template<typename _Up
>
449 using rebind_traits
= allocator_traits
<allocator
<_Up
>>;
452 * @brief Allocate memory.
453 * @param __a An allocator.
454 * @param __n The number of objects to allocate space for.
456 * Calls @c a.allocate(n)
458 _GLIBCXX_NODISCARD
static _GLIBCXX20_CONSTEXPR pointer
459 allocate(allocator_type
& __a
, size_type __n
)
460 { return __a
.allocate(__n
); }
463 * @brief Allocate memory.
464 * @param __a An allocator.
465 * @param __n The number of objects to allocate space for.
466 * @param __hint Aid to locality.
467 * @return Memory of suitable size and alignment for @a n objects
468 * of type @c value_type
470 * Returns <tt> a.allocate(n, hint) </tt>
472 _GLIBCXX_NODISCARD
static _GLIBCXX20_CONSTEXPR pointer
473 allocate(allocator_type
& __a
, size_type __n
, const_void_pointer __hint
)
475 #if __cplusplus <= 201703L
476 return __a
.allocate(__n
, __hint
);
478 return __a
.allocate(__n
);
483 * @brief Deallocate memory.
484 * @param __a An allocator.
485 * @param __p Pointer to the memory to deallocate.
486 * @param __n The number of objects space was allocated for.
488 * Calls <tt> a.deallocate(p, n) </tt>
490 static _GLIBCXX20_CONSTEXPR
void
491 deallocate(allocator_type
& __a
, pointer __p
, size_type __n
)
492 { __a
.deallocate(__p
, __n
); }
495 * @brief Construct an object of type `_Up`
496 * @param __a An allocator.
497 * @param __p Pointer to memory of suitable size and alignment for
498 * an object of type `_Up`.
499 * @param __args Constructor arguments.
501 * Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
502 * in C++11, C++14 and C++17. Changed in C++20 to call
503 * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
505 template<typename _Up
, typename
... _Args
>
506 static _GLIBCXX20_CONSTEXPR
void
507 construct(allocator_type
& __a
__attribute__((__unused__
)), _Up
* __p
,
509 noexcept(std::is_nothrow_constructible
<_Up
, _Args
...>::value
)
511 #if __cplusplus <= 201703L
512 __a
.construct(__p
, std::forward
<_Args
>(__args
)...);
514 std::construct_at(__p
, std::forward
<_Args
>(__args
)...);
519 * @brief Destroy an object of type @a _Up
520 * @param __a An allocator.
521 * @param __p Pointer to the object to destroy
523 * Calls @c __a.destroy(__p).
525 template<typename _Up
>
526 static _GLIBCXX20_CONSTEXPR
void
527 destroy(allocator_type
& __a
__attribute__((__unused__
)), _Up
* __p
)
528 noexcept(is_nothrow_destructible
<_Up
>::value
)
530 #if __cplusplus <= 201703L
533 std::destroy_at(__p
);
538 * @brief The maximum supported allocation size
539 * @param __a An allocator.
540 * @return @c __a.max_size()
542 static _GLIBCXX20_CONSTEXPR size_type
543 max_size(const allocator_type
& __a
__attribute__((__unused__
))) noexcept
545 #if __cplusplus <= 201703L
546 return __a
.max_size();
548 return size_t(-1) / sizeof(value_type
);
553 * @brief Obtain an allocator to use when copying a container.
554 * @param __rhs An allocator.
557 static _GLIBCXX20_CONSTEXPR allocator_type
558 select_on_container_copy_construction(const allocator_type
& __rhs
)
562 /// Explicit specialization for std::allocator<void>.
564 struct allocator_traits
<allocator
<void>>
566 /// The allocator type
567 using allocator_type
= allocator
<void>;
569 /// The allocated type
570 using value_type
= void;
572 /// The allocator's pointer type.
573 using pointer
= void*;
575 /// The allocator's const pointer type.
576 using const_pointer
= const void*;
578 /// The allocator's void pointer type.
579 using void_pointer
= void*;
581 /// The allocator's const void pointer type.
582 using const_void_pointer
= const void*;
584 /// The allocator's difference type
585 using difference_type
= std::ptrdiff_t;
587 /// The allocator's size type
588 using size_type
= std::size_t;
590 /// How the allocator is propagated on copy assignment
591 using propagate_on_container_copy_assignment
= false_type
;
593 /// How the allocator is propagated on move assignment
594 using propagate_on_container_move_assignment
= true_type
;
596 /// How the allocator is propagated on swap
597 using propagate_on_container_swap
= false_type
;
599 /// Whether all instances of the allocator type compare equal.
600 using is_always_equal
= true_type
;
602 template<typename _Up
>
603 using rebind_alloc
= allocator
<_Up
>;
605 template<typename _Up
>
606 using rebind_traits
= allocator_traits
<allocator
<_Up
>>;
608 /// allocate is ill-formed for allocator<void>
610 allocate(allocator_type
&, size_type
, const void* = nullptr) = delete;
612 /// deallocate is ill-formed for allocator<void>
614 deallocate(allocator_type
&, void*, size_type
) = delete;
617 * @brief Construct an object of type `_Up`
618 * @param __a An allocator.
619 * @param __p Pointer to memory of suitable size and alignment for
620 * an object of type `_Up`.
621 * @param __args Constructor arguments.
623 * Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
624 * in C++11, C++14 and C++17. Changed in C++20 to call
625 * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
627 template<typename _Up
, typename
... _Args
>
628 static _GLIBCXX20_CONSTEXPR
void
629 construct(allocator_type
&, _Up
* __p
, _Args
&&... __args
)
630 noexcept(std::is_nothrow_constructible
<_Up
, _Args
...>::value
)
632 #if __cplusplus <= 201703L
633 ::new((void *)__p
) _Up(std::forward
<_Args
>(__args
)...);
635 std::construct_at(__p
, std::forward
<_Args
>(__args
)...);
640 * @brief Destroy an object of type `_Up`
641 * @param __a An allocator.
642 * @param __p Pointer to the object to destroy
644 * Invokes the destructor for `*__p`.
646 template<typename _Up
>
647 static _GLIBCXX20_CONSTEXPR
void
648 destroy(allocator_type
&, _Up
* __p
)
649 noexcept(is_nothrow_destructible
<_Up
>::value
)
650 { std::_Destroy(__p
); }
652 /// max_size is ill-formed for allocator<void>
654 max_size(const allocator_type
&) = delete;
657 * @brief Obtain an allocator to use when copying a container.
658 * @param __rhs An allocator.
661 static _GLIBCXX20_CONSTEXPR allocator_type
662 select_on_container_copy_construction(const allocator_type
& __rhs
)
666 #if __cplusplus < 201703L
667 template<typename _Alloc
>
669 __do_alloc_on_copy(_Alloc
& __one
, const _Alloc
& __two
, true_type
)
672 template<typename _Alloc
>
674 __do_alloc_on_copy(_Alloc
&, const _Alloc
&, false_type
)
678 template<typename _Alloc
>
679 _GLIBCXX14_CONSTEXPR
inline void
680 __alloc_on_copy(_Alloc
& __one
, const _Alloc
& __two
)
682 typedef allocator_traits
<_Alloc
> __traits
;
683 typedef typename
__traits::propagate_on_container_copy_assignment __pocca
;
684 #if __cplusplus >= 201703L
685 if constexpr (__pocca::value
)
688 __do_alloc_on_copy(__one
, __two
, __pocca());
692 template<typename _Alloc
>
694 __alloc_on_copy(const _Alloc
& __a
)
696 typedef allocator_traits
<_Alloc
> __traits
;
697 return __traits::select_on_container_copy_construction(__a
);
700 #if __cplusplus < 201703L
701 template<typename _Alloc
>
702 inline void __do_alloc_on_move(_Alloc
& __one
, _Alloc
& __two
, true_type
)
703 { __one
= std::move(__two
); }
705 template<typename _Alloc
>
706 inline void __do_alloc_on_move(_Alloc
&, _Alloc
&, false_type
)
710 template<typename _Alloc
>
711 _GLIBCXX14_CONSTEXPR
inline void
712 __alloc_on_move(_Alloc
& __one
, _Alloc
& __two
)
714 typedef allocator_traits
<_Alloc
> __traits
;
715 typedef typename
__traits::propagate_on_container_move_assignment __pocma
;
716 #if __cplusplus >= 201703L
717 if constexpr (__pocma::value
)
718 __one
= std::move(__two
);
720 __do_alloc_on_move(__one
, __two
, __pocma());
724 #if __cplusplus < 201703L
725 template<typename _Alloc
>
726 inline void __do_alloc_on_swap(_Alloc
& __one
, _Alloc
& __two
, true_type
)
732 template<typename _Alloc
>
733 inline void __do_alloc_on_swap(_Alloc
&, _Alloc
&, false_type
)
737 template<typename _Alloc
>
738 _GLIBCXX14_CONSTEXPR
inline void
739 __alloc_on_swap(_Alloc
& __one
, _Alloc
& __two
)
741 typedef allocator_traits
<_Alloc
> __traits
;
742 typedef typename
__traits::propagate_on_container_swap __pocs
;
743 #if __cplusplus >= 201703L
744 if constexpr (__pocs::value
)
750 __do_alloc_on_swap(__one
, __two
, __pocs());
754 template<typename _Alloc
, typename _Tp
,
755 typename _ValueT
= __remove_cvref_t
<typename
_Alloc::value_type
>,
757 struct __is_alloc_insertable_impl
761 template<typename _Alloc
, typename _Tp
, typename _ValueT
>
762 struct __is_alloc_insertable_impl
<_Alloc
, _Tp
, _ValueT
,
763 __void_t
<decltype(allocator_traits
<_Alloc
>::construct(
764 std::declval
<_Alloc
&>(), std::declval
<_ValueT
*>(),
765 std::declval
<_Tp
>()))>>
769 // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
770 // (might be wrong if _Alloc::construct exists but is not constrained,
771 // i.e. actually trying to use it would still be invalid. Use with caution.)
772 template<typename _Alloc
>
773 struct __is_copy_insertable
774 : __is_alloc_insertable_impl
<_Alloc
,
775 typename
_Alloc::value_type
const&>::type
778 // std::allocator<_Tp> just requires CopyConstructible
779 template<typename _Tp
>
780 struct __is_copy_insertable
<allocator
<_Tp
>>
781 : is_copy_constructible
<_Tp
>
784 // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
785 // (might be wrong if _Alloc::construct exists but is not constrained,
786 // i.e. actually trying to use it would still be invalid. Use with caution.)
787 template<typename _Alloc
>
788 struct __is_move_insertable
789 : __is_alloc_insertable_impl
<_Alloc
, typename
_Alloc::value_type
>::type
792 // std::allocator<_Tp> just requires MoveConstructible
793 template<typename _Tp
>
794 struct __is_move_insertable
<allocator
<_Tp
>>
795 : is_move_constructible
<_Tp
>
798 // Trait to detect Allocator-like types.
799 template<typename _Alloc
, typename
= void>
800 struct __is_allocator
: false_type
{ };
802 template<typename _Alloc
>
803 struct __is_allocator
<_Alloc
,
804 __void_t
<typename
_Alloc::value_type
,
805 decltype(std::declval
<_Alloc
&>().allocate(size_t{}))>>
808 template<typename _Alloc
>
809 using _RequireAllocator
810 = typename enable_if
<__is_allocator
<_Alloc
>::value
, _Alloc
>::type
;
812 template<typename _Alloc
>
813 using _RequireNotAllocator
814 = typename enable_if
<!__is_allocator
<_Alloc
>::value
, _Alloc
>::type
;
816 #if __cpp_concepts >= 201907L
817 template<typename _Alloc
>
818 concept __allocator_like
= requires (_Alloc
& __a
) {
819 typename
_Alloc::value_type
;
820 __a
.deallocate(__a
.allocate(1u), 1u);
826 * Destroy a range of objects using the supplied allocator. For
827 * non-default allocators we do not optimize away invocation of
828 * destroy() even if _Tp has a trivial destructor.
831 template<typename _ForwardIterator
, typename _Allocator
>
833 _Destroy(_ForwardIterator __first
, _ForwardIterator __last
,
836 for (; __first
!= __last
; ++__first
)
837 #if __cplusplus < 201103L
838 __alloc
.destroy(std::__addressof(*__first
));
840 allocator_traits
<_Allocator
>::destroy(__alloc
,
841 std::__addressof(*__first
));
845 template<typename _ForwardIterator
, typename _Tp
>
847 _Destroy(_ForwardIterator __first
, _ForwardIterator __last
,
850 _Destroy(__first
, __last
);
853 _GLIBCXX_END_NAMESPACE_VERSION
855 #endif // _ALLOC_TRAITS_H