libstdc++
bits/alloc_traits.h
Go to the documentation of this file.
1// Allocator traits -*- C++ -*-
2
3// Copyright (C) 2011-2020 Free Software Foundation, Inc.
4//
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)
9// any later version.
10
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.
15
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.
19
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/>.
24
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}
28 */
29
30#ifndef _ALLOC_TRAITS_H
31#define _ALLOC_TRAITS_H 1
32
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>
39#endif
40
41namespace std _GLIBCXX_VISIBILITY(default)
42{
43_GLIBCXX_BEGIN_NAMESPACE_VERSION
44
45#if __cplusplus >= 201103L
46#define __cpp_lib_allocator_traits_is_always_equal 201411
47
48 struct __allocator_traits_base
49 {
50 template<typename _Tp, typename _Up, typename = void>
51 struct __rebind : __replace_first_arg<_Tp, _Up> { };
52
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; };
57
58 protected:
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;
75 };
76
77 template<typename _Alloc, typename _Up>
78 using __alloc_rebind
79 = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
80
81 /**
82 * @brief Uniform interface to all allocator types.
83 * @ingroup allocators
84 */
85 template<typename _Alloc>
86 struct allocator_traits : __allocator_traits_base
87 {
88 /// The allocator type
89 typedef _Alloc allocator_type;
90 /// The allocated type
91 typedef typename _Alloc::value_type value_type;
92
93 /**
94 * @brief The allocator's pointer type.
95 *
96 * @c Alloc::pointer if that type exists, otherwise @c value_type*
97 */
98 using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
99
100 private:
101 // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
102 template<template<typename> class _Func, typename _Tp, typename = void>
103 struct _Ptr
104 {
105 using type = typename pointer_traits<pointer>::template rebind<_Tp>;
106 };
107
108 template<template<typename> class _Func, typename _Tp>
109 struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
110 {
111 using type = _Func<_Alloc>;
112 };
113
114 // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
115 template<typename _A2, typename _PtrT, typename = void>
116 struct _Diff
117 { using type = typename pointer_traits<_PtrT>::difference_type; };
118
119 template<typename _A2, typename _PtrT>
120 struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
121 { using type = typename _A2::difference_type; };
122
123 // Select _A2::size_type or make_unsigned<_DiffT>::type
124 template<typename _A2, typename _DiffT, typename = void>
125 struct _Size : make_unsigned<_DiffT> { };
126
127 template<typename _A2, typename _DiffT>
128 struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
129 { using type = typename _A2::size_type; };
130
131 public:
132 /**
133 * @brief The allocator's const pointer type.
134 *
135 * @c Alloc::const_pointer if that type exists, otherwise
136 * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
137 */
138 using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
139
140 /**
141 * @brief The allocator's void pointer type.
142 *
143 * @c Alloc::void_pointer if that type exists, otherwise
144 * <tt> pointer_traits<pointer>::rebind<void> </tt>
145 */
146 using void_pointer = typename _Ptr<__v_pointer, void>::type;
147
148 /**
149 * @brief The allocator's const void pointer type.
150 *
151 * @c Alloc::const_void_pointer if that type exists, otherwise
152 * <tt> pointer_traits<pointer>::rebind<const void> </tt>
153 */
154 using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
155
156 /**
157 * @brief The allocator's difference type
158 *
159 * @c Alloc::difference_type if that type exists, otherwise
160 * <tt> pointer_traits<pointer>::difference_type </tt>
161 */
162 using difference_type = typename _Diff<_Alloc, pointer>::type;
163
164 /**
165 * @brief The allocator's size type
166 *
167 * @c Alloc::size_type if that type exists, otherwise
168 * <tt> make_unsigned<difference_type>::type </tt>
169 */
170 using size_type = typename _Size<_Alloc, difference_type>::type;
171
172 /**
173 * @brief How the allocator is propagated on copy assignment
174 *
175 * @c Alloc::propagate_on_container_copy_assignment if that type exists,
176 * otherwise @c false_type
177 */
179 = __detected_or_t<false_type, __pocca, _Alloc>;
180
181 /**
182 * @brief How the allocator is propagated on move assignment
183 *
184 * @c Alloc::propagate_on_container_move_assignment if that type exists,
185 * otherwise @c false_type
186 */
188 = __detected_or_t<false_type, __pocma, _Alloc>;
189
190 /**
191 * @brief How the allocator is propagated on swap
192 *
193 * @c Alloc::propagate_on_container_swap if that type exists,
194 * otherwise @c false_type
195 */
197 = __detected_or_t<false_type, __pocs, _Alloc>;
198
199 /**
200 * @brief Whether all instances of the allocator type compare equal.
201 *
202 * @c Alloc::is_always_equal if that type exists,
203 * otherwise @c is_empty<Alloc>::type
204 */
206 = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
207
208 template<typename _Tp>
209 using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
210 template<typename _Tp>
212
213 private:
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); }
219
220 template<typename _Alloc2>
221 static constexpr pointer
222 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
223 { return __a.allocate(__n); }
224
225 template<typename _Tp, typename... _Args>
226 struct __construct_helper
227 {
228 template<typename _Alloc2,
229 typename = decltype(std::declval<_Alloc2*>()->construct(
230 std::declval<_Tp*>(), std::declval<_Args>()...))>
231 static true_type __test(int);
232
233 template<typename>
234 static false_type __test(...);
235
236 using type = decltype(__test<_Alloc>(0));
237 };
238
239 template<typename _Tp, typename... _Args>
240 using __has_construct
241 = typename __construct_helper<_Tp, _Args...>::type;
242
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)...); }
248
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)
255 {
256#if __cplusplus <= 201703L
257 ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
258#else
259 std::construct_at(__p, std::forward<_Args>(__args)...);
260#endif
261 }
262
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); }
269
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); }
275
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(); }
281
282 template<typename _Alloc2>
283 static constexpr size_type
284 _S_max_size(_Alloc2&, ...)
285 {
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);
290 }
291
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(); }
297
298 template<typename _Alloc2>
299 static constexpr _Alloc2
300 _S_select(_Alloc2& __a, ...)
301 { return __a; }
302
303 public:
304
305 /**
306 * @brief Allocate memory.
307 * @param __a An allocator.
308 * @param __n The number of objects to allocate space for.
309 *
310 * Calls @c a.allocate(n)
311 */
312 _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
313 allocate(_Alloc& __a, size_type __n)
314 { return __a.allocate(__n); }
315
316 /**
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
323 *
324 * Returns <tt> a.allocate(n, hint) </tt> if that expression is
325 * well-formed, otherwise returns @c a.allocate(n)
326 */
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); }
330
331 /**
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.
336 *
337 * Calls <tt> a.deallocate(p, n) </tt>
338 */
339 static _GLIBCXX20_CONSTEXPR void
340 deallocate(_Alloc& __a, pointer __p, size_type __n)
341 { __a.deallocate(__p, __n); }
342
343 /**
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.
348 *
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...
353 */
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)...); }
361
362 /**
363 * @brief Destroy an object of type @a _Tp
364 * @param __a An allocator.
365 * @param __p Pointer to the object to destroy
366 *
367 * Calls @c __a.destroy(__p) if that expression is well-formed,
368 * otherwise calls @c __p->~_Tp()
369 */
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); }
375
376 /**
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()
380 *
381 * Returns @c __a.max_size() if that expression is well-formed,
382 * otherwise returns @c numeric_limits<size_type>::max()
383 */
384 static _GLIBCXX20_CONSTEXPR size_type
385 max_size(const _Alloc& __a) noexcept
386 { return _S_max_size(__a, 0); }
387
388 /**
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
392 *
393 * Returns @c __rhs.select_on_container_copy_construction() if that
394 * expression is well-formed, otherwise returns @a __rhs
395 */
396 static _GLIBCXX20_CONSTEXPR _Alloc
398 { return _S_select(__rhs, 0); }
399 };
400
401#if __cplusplus > 201703L
402# define __cpp_lib_constexpr_dynamic_alloc 201907L
403#endif
404
405 /// Partial specialization for std::allocator.
406 template<typename _Tp>
408 {
409 /// The allocator type
411
412 /// The allocated type
413 using value_type = _Tp;
414
415 /// The allocator's pointer type.
416 using pointer = _Tp*;
417
418 /// The allocator's const pointer type.
419 using const_pointer = const _Tp*;
420
421 /// The allocator's void pointer type.
422 using void_pointer = void*;
423
424 /// The allocator's const void pointer type.
425 using const_void_pointer = const void*;
426
427 /// The allocator's difference type
428 using difference_type = std::ptrdiff_t;
429
430 /// The allocator's size type
431 using size_type = std::size_t;
432
433 /// How the allocator is propagated on copy assignment
435
436 /// How the allocator is propagated on move assignment
438
439 /// How the allocator is propagated on swap
441
442 /// Whether all instances of the allocator type compare equal.
444
445 template<typename _Up>
447
448 template<typename _Up>
450
451 /**
452 * @brief Allocate memory.
453 * @param __a An allocator.
454 * @param __n The number of objects to allocate space for.
455 *
456 * Calls @c a.allocate(n)
457 */
458 _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
460 { return __a.allocate(__n); }
461
462 /**
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
469 *
470 * Returns <tt> a.allocate(n, hint) </tt>
471 */
472 _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
474 {
475#if __cplusplus <= 201703L
476 return __a.allocate(__n, __hint);
477#else
478 return __a.allocate(__n);
479#endif
480 }
481
482 /**
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.
487 *
488 * Calls <tt> a.deallocate(p, n) </tt>
489 */
490 static _GLIBCXX20_CONSTEXPR void
492 { __a.deallocate(__p, __n); }
493
494 /**
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.
500 *
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.
504 */
505 template<typename _Up, typename... _Args>
506 static _GLIBCXX20_CONSTEXPR void
507 construct(allocator_type& __a __attribute__((__unused__)), _Up* __p,
508 _Args&&... __args)
509 noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
510 {
511#if __cplusplus <= 201703L
512 __a.construct(__p, std::forward<_Args>(__args)...);
513#else
514 std::construct_at(__p, std::forward<_Args>(__args)...);
515#endif
516 }
517
518 /**
519 * @brief Destroy an object of type @a _Up
520 * @param __a An allocator.
521 * @param __p Pointer to the object to destroy
522 *
523 * Calls @c __a.destroy(__p).
524 */
525 template<typename _Up>
526 static _GLIBCXX20_CONSTEXPR void
527 destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p)
529 {
530#if __cplusplus <= 201703L
531 __a.destroy(__p);
532#else
533 std::destroy_at(__p);
534#endif
535 }
536
537 /**
538 * @brief The maximum supported allocation size
539 * @param __a An allocator.
540 * @return @c __a.max_size()
541 */
542 static _GLIBCXX20_CONSTEXPR size_type
543 max_size(const allocator_type& __a __attribute__((__unused__))) noexcept
544 {
545#if __cplusplus <= 201703L
546 return __a.max_size();
547#else
548 return size_t(-1) / sizeof(value_type);
549#endif
550 }
551
552 /**
553 * @brief Obtain an allocator to use when copying a container.
554 * @param __rhs An allocator.
555 * @return @c __rhs
556 */
557 static _GLIBCXX20_CONSTEXPR allocator_type
559 { return __rhs; }
560 };
561
562 /// Explicit specialization for std::allocator<void>.
563 template<>
565 {
566 /// The allocator type
568
569 /// The allocated type
570 using value_type = void;
571
572 /// The allocator's pointer type.
573 using pointer = void*;
574
575 /// The allocator's const pointer type.
576 using const_pointer = const void*;
577
578 /// The allocator's void pointer type.
579 using void_pointer = void*;
580
581 /// The allocator's const void pointer type.
582 using const_void_pointer = const void*;
583
584 /// The allocator's difference type
585 using difference_type = std::ptrdiff_t;
586
587 /// The allocator's size type
588 using size_type = std::size_t;
589
590 /// How the allocator is propagated on copy assignment
592
593 /// How the allocator is propagated on move assignment
595
596 /// How the allocator is propagated on swap
598
599 /// Whether all instances of the allocator type compare equal.
601
602 template<typename _Up>
604
605 template<typename _Up>
607
608 /// allocate is ill-formed for allocator<void>
609 static void*
610 allocate(allocator_type&, size_type, const void* = nullptr) = delete;
611
612 /// deallocate is ill-formed for allocator<void>
613 static void
615
616 /**
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.
622 *
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.
626 */
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)
631 {
632#if __cplusplus <= 201703L
633 ::new((void *)__p) _Up(std::forward<_Args>(__args)...);
634#else
635 std::construct_at(__p, std::forward<_Args>(__args)...);
636#endif
637 }
638
639 /**
640 * @brief Destroy an object of type `_Up`
641 * @param __a An allocator.
642 * @param __p Pointer to the object to destroy
643 *
644 * Invokes the destructor for `*__p`.
645 */
646 template<typename _Up>
647 static _GLIBCXX20_CONSTEXPR void
650 { std::_Destroy(__p); }
651
652 /// max_size is ill-formed for allocator<void>
653 static size_type
654 max_size(const allocator_type&) = delete;
655
656 /**
657 * @brief Obtain an allocator to use when copying a container.
658 * @param __rhs An allocator.
659 * @return `__rhs`
660 */
661 static _GLIBCXX20_CONSTEXPR allocator_type
663 { return __rhs; }
664 };
665
666#if __cplusplus < 201703L
667 template<typename _Alloc>
668 inline void
669 __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
670 { __one = __two; }
671
672 template<typename _Alloc>
673 inline void
674 __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
675 { }
676#endif
677
678 template<typename _Alloc>
679 _GLIBCXX14_CONSTEXPR inline void
680 __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
681 {
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)
686 __one = __two;
687#else
688 __do_alloc_on_copy(__one, __two, __pocca());
689#endif
690 }
691
692 template<typename _Alloc>
693 constexpr _Alloc
694 __alloc_on_copy(const _Alloc& __a)
695 {
696 typedef allocator_traits<_Alloc> __traits;
697 return __traits::select_on_container_copy_construction(__a);
698 }
699
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); }
704
705 template<typename _Alloc>
706 inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
707 { }
708#endif
709
710 template<typename _Alloc>
711 _GLIBCXX14_CONSTEXPR inline void
712 __alloc_on_move(_Alloc& __one, _Alloc& __two)
713 {
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);
719#else
720 __do_alloc_on_move(__one, __two, __pocma());
721#endif
722 }
723
724#if __cplusplus < 201703L
725 template<typename _Alloc>
726 inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
727 {
728 using std::swap;
729 swap(__one, __two);
730 }
731
732 template<typename _Alloc>
733 inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
734 { }
735#endif
736
737 template<typename _Alloc>
738 _GLIBCXX14_CONSTEXPR inline void
739 __alloc_on_swap(_Alloc& __one, _Alloc& __two)
740 {
741 typedef allocator_traits<_Alloc> __traits;
742 typedef typename __traits::propagate_on_container_swap __pocs;
743#if __cplusplus >= 201703L
744 if constexpr (__pocs::value)
745 {
746 using std::swap;
747 swap(__one, __two);
748 }
749#else
750 __do_alloc_on_swap(__one, __two, __pocs());
751#endif
752 }
753
754 template<typename _Alloc, typename _Tp,
755 typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
756 typename = void>
757 struct __is_alloc_insertable_impl
758 : false_type
759 { };
760
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>()))>>
766 : true_type
767 { };
768
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
776 { };
777
778 // std::allocator<_Tp> just requires CopyConstructible
779 template<typename _Tp>
780 struct __is_copy_insertable<allocator<_Tp>>
781 : is_copy_constructible<_Tp>
782 { };
783
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
790 { };
791
792 // std::allocator<_Tp> just requires MoveConstructible
793 template<typename _Tp>
794 struct __is_move_insertable<allocator<_Tp>>
795 : is_move_constructible<_Tp>
796 { };
797
798 // Trait to detect Allocator-like types.
799 template<typename _Alloc, typename = void>
800 struct __is_allocator : false_type { };
801
802 template<typename _Alloc>
803 struct __is_allocator<_Alloc,
804 __void_t<typename _Alloc::value_type,
805 decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
806 : true_type { };
807
808 template<typename _Alloc>
809 using _RequireAllocator
810 = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
811
812 template<typename _Alloc>
813 using _RequireNotAllocator
814 = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
815#endif // C++11
816
817 /**
818 * Destroy a range of objects using the supplied allocator. For
819 * non-default allocators we do not optimize away invocation of
820 * destroy() even if _Tp has a trivial destructor.
821 */
822
823 template<typename _ForwardIterator, typename _Allocator>
824 void
825 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
826 _Allocator& __alloc)
827 {
828 for (; __first != __last; ++__first)
829#if __cplusplus < 201103L
830 __alloc.destroy(std::__addressof(*__first));
831#else
833 std::__addressof(*__first));
834#endif
835 }
836
837 template<typename _ForwardIterator, typename _Tp>
838 inline void
839 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
840 allocator<_Tp>&)
841 {
842 _Destroy(__first, __last);
843 }
844
845_GLIBCXX_END_NAMESPACE_VERSION
846} // namespace std
847#endif // _ALLOC_TRAITS_H
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:75
integral_constant< bool, false > false_type
The type used as a compile-time boolean with false value.
Definition: type_traits:78
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:101
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:49
ISO C++ entities toplevel namespace is std.
void _Destroy(_ForwardIterator __first, _ForwardIterator __last, _Allocator &__alloc)
integral_constant
Definition: type_traits:58
is_nothrow_destructible
Definition: type_traits:894
is_nothrow_constructible
Definition: type_traits:1010
Uniform interface to all allocator types.
static constexpr auto construct(_Alloc &__a, _Tp *__p, _Args &&... __args) noexcept(noexcept(_S_construct(__a, __p, std::forward< _Args >(__args)...))) -> decltype(_S_construct(__a, __p, std::forward< _Args >(__args)...))
Construct an object of type _Tp
__detected_or_t< false_type, __pocma, _Alloc > propagate_on_container_move_assignment
How the allocator is propagated on move assignment.
typename _Ptr< __v_pointer, void >::type void_pointer
The allocator's void pointer type.
__detected_or_t< value_type *, __pointer, _Alloc > pointer
The allocator's pointer type.
static constexpr pointer allocate(_Alloc &__a, size_type __n)
Allocate memory.
static constexpr pointer allocate(_Alloc &__a, size_type __n, const_void_pointer __hint)
Allocate memory.
typename _Size< _Alloc, difference_type >::type size_type
The allocator's size type.
typename _Ptr< __cv_pointer, const void >::type const_void_pointer
The allocator's const void pointer type.
typename _Diff< _Alloc, pointer >::type difference_type
The allocator's difference type.
typename _Ptr< __c_pointer, const value_type >::type const_pointer
The allocator's const pointer type.
_Alloc::value_type value_type
The allocated type.
static constexpr void deallocate(_Alloc &__a, pointer __p, size_type __n)
Deallocate memory.
static constexpr size_type max_size(const _Alloc &__a) noexcept
The maximum supported allocation size.
__detected_or_t< false_type, __pocca, _Alloc > propagate_on_container_copy_assignment
How the allocator is propagated on copy assignment.
static constexpr void destroy(_Alloc &__a, _Tp *__p) noexcept(noexcept(_S_destroy(__a, __p, 0)))
Destroy an object of type _Tp.
static constexpr _Alloc select_on_container_copy_construction(const _Alloc &__rhs)
Obtain an allocator to use when copying a container.
__detected_or_t< false_type, __pocs, _Alloc > propagate_on_container_swap
How the allocator is propagated on swap.
__detected_or_t< typename is_empty< _Alloc >::type, __equal, _Alloc > is_always_equal
Whether all instances of the allocator type compare equal.
_Alloc allocator_type
The allocator type.
allocator< _Tp > allocator_type
The allocator type.
void * void_pointer
The allocator's void pointer type.
_Tp * pointer
The allocator's pointer type.
static constexpr pointer allocate(allocator_type &__a, size_type __n)
Allocate memory.
static constexpr pointer allocate(allocator_type &__a, size_type __n, const_void_pointer __hint)
Allocate memory.
std::ptrdiff_t difference_type
The allocator's difference type.
const _Tp * const_pointer
The allocator's const pointer type.
const void * const_void_pointer
The allocator's const void pointer type.
static constexpr void deallocate(allocator_type &__a, pointer __p, size_type __n)
Deallocate memory.
static constexpr size_type max_size(const allocator_type &__a) noexcept
The maximum supported allocation size.
static constexpr allocator_type select_on_container_copy_construction(const allocator_type &__rhs)
Obtain an allocator to use when copying a container.
static constexpr void construct(allocator_type &__a, _Up *__p, _Args &&... __args) noexcept(std::is_nothrow_constructible< _Up, _Args... >::value)
Construct an object of type _Up
static constexpr void destroy(allocator_type &__a, _Up *__p) noexcept(is_nothrow_destructible< _Up >::value)
Destroy an object of type _Up.
std::size_t size_type
The allocator's size type.
void * pointer
The allocator's pointer type.
void * void_pointer
The allocator's void pointer type.
static void deallocate(allocator_type &, void *, size_type)=delete
deallocate is ill-formed for allocator<void>
static constexpr void construct(allocator_type &, _Up *__p, _Args &&... __args) noexcept(std::is_nothrow_constructible< _Up, _Args... >::value)
Construct an object of type _Up
static size_type max_size(const allocator_type &)=delete
max_size is ill-formed for allocator<void>
std::size_t size_type
The allocator's size type.
const void * const_pointer
The allocator's const pointer type.
std::ptrdiff_t difference_type
The allocator's difference type.
static void * allocate(allocator_type &, size_type, const void *=nullptr)=delete
allocate is ill-formed for allocator<void>
static constexpr allocator_type select_on_container_copy_construction(const allocator_type &__rhs)
Obtain an allocator to use when copying a container.
const void * const_void_pointer
The allocator's const void pointer type.
static constexpr void destroy(allocator_type &, _Up *__p) noexcept(is_nothrow_destructible< _Up >::value)
Destroy an object of type _Up
allocator<void> specialization.
Definition: allocator.h:73
The standard allocator, as per C++03 [20.4.1].
Definition: allocator.h:123
Uniform interface to all pointer-like types.
Definition: ptr_traits.h:84
__detected_or_t< ptrdiff_t, __difference_type, _Ptr > difference_type
The type used to represent the difference between two pointers.
Definition: ptr_traits.h:109