1// Allocator traits -*- C++ -*-
2
3// Copyright (C) 2011-2022 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 201411L
47
48  /// @cond undocumented
49  struct __allocator_traits_base
50  {
51    template<typename _Tp, typename _Up, typename = void>
52      struct __rebind : __replace_first_arg<_Tp, _Up> { };
53
54    template<typename _Tp, typename _Up>
55      struct __rebind<_Tp, _Up,
56		      __void_t<typename _Tp::template rebind<_Up>::other>>
57      { using type = typename _Tp::template rebind<_Up>::other; };
58
59  protected:
60    template<typename _Tp>
61      using __pointer = typename _Tp::pointer;
62    template<typename _Tp>
63      using __c_pointer = typename _Tp::const_pointer;
64    template<typename _Tp>
65      using __v_pointer = typename _Tp::void_pointer;
66    template<typename _Tp>
67      using __cv_pointer = typename _Tp::const_void_pointer;
68    template<typename _Tp>
69      using __pocca = typename _Tp::propagate_on_container_copy_assignment;
70    template<typename _Tp>
71      using __pocma = typename _Tp::propagate_on_container_move_assignment;
72    template<typename _Tp>
73      using __pocs = typename _Tp::propagate_on_container_swap;
74    template<typename _Tp>
75      using __equal = typename _Tp::is_always_equal;
76  };
77
78  template<typename _Alloc, typename _Up>
79    using __alloc_rebind
80      = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
81  /// @endcond
82
83  /**
84   * @brief  Uniform interface to all allocator types.
85   * @headerfile memory
86   * @ingroup allocators
87   * @since C++11
88  */
89  template<typename _Alloc>
90    struct allocator_traits : __allocator_traits_base
91    {
92      /// The allocator type
93      typedef _Alloc allocator_type;
94      /// The allocated type
95      typedef typename _Alloc::value_type value_type;
96
97      /**
98       * @brief   The allocator's pointer type.
99       *
100       * @c Alloc::pointer if that type exists, otherwise @c value_type*
101      */
102      using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
103
104    private:
105      // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
106      template<template<typename> class _Func, typename _Tp, typename = void>
107	struct _Ptr
108	{
109	  using type = typename pointer_traits<pointer>::template rebind<_Tp>;
110	};
111
112      template<template<typename> class _Func, typename _Tp>
113	struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
114	{
115	  using type = _Func<_Alloc>;
116	};
117
118      // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
119      template<typename _A2, typename _PtrT, typename = void>
120	struct _Diff
121	{ using type = typename pointer_traits<_PtrT>::difference_type; };
122
123      template<typename _A2, typename _PtrT>
124	struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
125	{ using type = typename _A2::difference_type; };
126
127      // Select _A2::size_type or make_unsigned<_DiffT>::type
128      template<typename _A2, typename _DiffT, typename = void>
129	struct _Size : make_unsigned<_DiffT> { };
130
131      template<typename _A2, typename _DiffT>
132	struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
133	{ using type = typename _A2::size_type; };
134
135    public:
136      /**
137       * @brief   The allocator's const pointer type.
138       *
139       * @c Alloc::const_pointer if that type exists, otherwise
140       * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
141      */
142      using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
143
144      /**
145       * @brief   The allocator's void pointer type.
146       *
147       * @c Alloc::void_pointer if that type exists, otherwise
148       * <tt> pointer_traits<pointer>::rebind<void> </tt>
149      */
150      using void_pointer = typename _Ptr<__v_pointer, void>::type;
151
152      /**
153       * @brief   The allocator's const void pointer type.
154       *
155       * @c Alloc::const_void_pointer if that type exists, otherwise
156       * <tt> pointer_traits<pointer>::rebind<const void> </tt>
157      */
158      using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
159
160      /**
161       * @brief   The allocator's difference type
162       *
163       * @c Alloc::difference_type if that type exists, otherwise
164       * <tt> pointer_traits<pointer>::difference_type </tt>
165      */
166      using difference_type = typename _Diff<_Alloc, pointer>::type;
167
168      /**
169       * @brief   The allocator's size type
170       *
171       * @c Alloc::size_type if that type exists, otherwise
172       * <tt> make_unsigned<difference_type>::type </tt>
173      */
174      using size_type = typename _Size<_Alloc, difference_type>::type;
175
176      /**
177       * @brief   How the allocator is propagated on copy assignment
178       *
179       * @c Alloc::propagate_on_container_copy_assignment if that type exists,
180       * otherwise @c false_type
181      */
182      using propagate_on_container_copy_assignment
183	= __detected_or_t<false_type, __pocca, _Alloc>;
184
185      /**
186       * @brief   How the allocator is propagated on move assignment
187       *
188       * @c Alloc::propagate_on_container_move_assignment if that type exists,
189       * otherwise @c false_type
190      */
191      using propagate_on_container_move_assignment
192	= __detected_or_t<false_type, __pocma, _Alloc>;
193
194      /**
195       * @brief   How the allocator is propagated on swap
196       *
197       * @c Alloc::propagate_on_container_swap if that type exists,
198       * otherwise @c false_type
199      */
200      using propagate_on_container_swap
201	= __detected_or_t<false_type, __pocs, _Alloc>;
202
203      /**
204       * @brief   Whether all instances of the allocator type compare equal.
205       *
206       * @c Alloc::is_always_equal if that type exists,
207       * otherwise @c is_empty<Alloc>::type
208      */
209      using is_always_equal
210	= __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
211
212      template<typename _Tp>
213	using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
214      template<typename _Tp>
215	using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
216
217    private:
218      template<typename _Alloc2>
219	static constexpr auto
220	_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
221	-> decltype(__a.allocate(__n, __hint))
222	{ return __a.allocate(__n, __hint); }
223
224      template<typename _Alloc2>
225	static constexpr pointer
226	_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
227	{ return __a.allocate(__n); }
228
229      template<typename _Tp, typename... _Args>
230	struct __construct_helper
231	{
232	  template<typename _Alloc2,
233	    typename = decltype(std::declval<_Alloc2*>()->construct(
234		  std::declval<_Tp*>(), std::declval<_Args>()...))>
235	    static true_type __test(int);
236
237	  template<typename>
238	    static false_type __test(...);
239
240	  using type = decltype(__test<_Alloc>(0));
241	};
242
243      template<typename _Tp, typename... _Args>
244	using __has_construct
245	  = typename __construct_helper<_Tp, _Args...>::type;
246
247      template<typename _Tp, typename... _Args>
248	static _GLIBCXX14_CONSTEXPR _Require<__has_construct<_Tp, _Args...>>
249	_S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
250	noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
251	{ __a.construct(__p, std::forward<_Args>(__args)...); }
252
253      template<typename _Tp, typename... _Args>
254	static _GLIBCXX14_CONSTEXPR
255	_Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
256			       is_constructible<_Tp, _Args...>>>
257	_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
258	noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value)
259	{
260#if __cplusplus <= 201703L
261	  ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
262#else
263	  std::construct_at(__p, std::forward<_Args>(__args)...);
264#endif
265	}
266
267      template<typename _Alloc2, typename _Tp>
268	static _GLIBCXX14_CONSTEXPR auto
269	_S_destroy(_Alloc2& __a, _Tp* __p, int)
270	noexcept(noexcept(__a.destroy(__p)))
271	-> decltype(__a.destroy(__p))
272	{ __a.destroy(__p); }
273
274      template<typename _Alloc2, typename _Tp>
275	static _GLIBCXX14_CONSTEXPR void
276	_S_destroy(_Alloc2&, _Tp* __p, ...)
277	noexcept(std::is_nothrow_destructible<_Tp>::value)
278	{ std::_Destroy(__p); }
279
280      template<typename _Alloc2>
281	static constexpr auto
282	_S_max_size(_Alloc2& __a, int)
283	-> decltype(__a.max_size())
284	{ return __a.max_size(); }
285
286      template<typename _Alloc2>
287	static constexpr size_type
288	_S_max_size(_Alloc2&, ...)
289	{
290	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
291	  // 2466. allocator_traits::max_size() default behavior is incorrect
292	  return __gnu_cxx::__numeric_traits<size_type>::__max
293	    / sizeof(value_type);
294	}
295
296      template<typename _Alloc2>
297	static constexpr auto
298	_S_select(_Alloc2& __a, int)
299	-> decltype(__a.select_on_container_copy_construction())
300	{ return __a.select_on_container_copy_construction(); }
301
302      template<typename _Alloc2>
303	static constexpr _Alloc2
304	_S_select(_Alloc2& __a, ...)
305	{ return __a; }
306
307    public:
308
309      /**
310       *  @brief  Allocate memory.
311       *  @param  __a  An allocator.
312       *  @param  __n  The number of objects to allocate space for.
313       *
314       *  Calls @c a.allocate(n)
315      */
316      _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
317      allocate(_Alloc& __a, size_type __n)
318      { return __a.allocate(__n); }
319
320      /**
321       *  @brief  Allocate memory.
322       *  @param  __a  An allocator.
323       *  @param  __n  The number of objects to allocate space for.
324       *  @param  __hint Aid to locality.
325       *  @return Memory of suitable size and alignment for @a n objects
326       *          of type @c value_type
327       *
328       *  Returns <tt> a.allocate(n, hint) </tt> if that expression is
329       *  well-formed, otherwise returns @c a.allocate(n)
330      */
331      _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
332      allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
333      { return _S_allocate(__a, __n, __hint, 0); }
334
335      /**
336       *  @brief  Deallocate memory.
337       *  @param  __a  An allocator.
338       *  @param  __p  Pointer to the memory to deallocate.
339       *  @param  __n  The number of objects space was allocated for.
340       *
341       *  Calls <tt> a.deallocate(p, n) </tt>
342      */
343      static _GLIBCXX20_CONSTEXPR void
344      deallocate(_Alloc& __a, pointer __p, size_type __n)
345      { __a.deallocate(__p, __n); }
346
347      /**
348       *  @brief  Construct an object of type `_Tp`
349       *  @param  __a  An allocator.
350       *  @param  __p  Pointer to memory of suitable size and alignment for Tp
351       *  @param  __args Constructor arguments.
352       *
353       *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
354       *  if that expression is well-formed, otherwise uses placement-new
355       *  to construct an object of type @a _Tp at location @a __p from the
356       *  arguments @a __args...
357      */
358      template<typename _Tp, typename... _Args>
359	static _GLIBCXX20_CONSTEXPR auto
360	construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
361	noexcept(noexcept(_S_construct(__a, __p,
362				       std::forward<_Args>(__args)...)))
363	-> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
364	{ _S_construct(__a, __p, std::forward<_Args>(__args)...); }
365
366      /**
367       *  @brief  Destroy an object of type @a _Tp
368       *  @param  __a  An allocator.
369       *  @param  __p  Pointer to the object to destroy
370       *
371       *  Calls @c __a.destroy(__p) if that expression is well-formed,
372       *  otherwise calls @c __p->~_Tp()
373      */
374      template<typename _Tp>
375	static _GLIBCXX20_CONSTEXPR void
376	destroy(_Alloc& __a, _Tp* __p)
377	noexcept(noexcept(_S_destroy(__a, __p, 0)))
378	{ _S_destroy(__a, __p, 0); }
379
380      /**
381       *  @brief  The maximum supported allocation size
382       *  @param  __a  An allocator.
383       *  @return @c __a.max_size() or @c numeric_limits<size_type>::max()
384       *
385       *  Returns @c __a.max_size() if that expression is well-formed,
386       *  otherwise returns @c numeric_limits<size_type>::max()
387      */
388      static _GLIBCXX20_CONSTEXPR size_type
389      max_size(const _Alloc& __a) noexcept
390      { return _S_max_size(__a, 0); }
391
392      /**
393       *  @brief  Obtain an allocator to use when copying a container.
394       *  @param  __rhs  An allocator.
395       *  @return @c __rhs.select_on_container_copy_construction() or @a __rhs
396       *
397       *  Returns @c __rhs.select_on_container_copy_construction() if that
398       *  expression is well-formed, otherwise returns @a __rhs
399      */
400      static _GLIBCXX20_CONSTEXPR _Alloc
401      select_on_container_copy_construction(const _Alloc& __rhs)
402      { return _S_select(__rhs, 0); }
403    };
404
405#if __cplusplus > 201703L
406# define __cpp_lib_constexpr_dynamic_alloc 201907L
407#endif
408
409  /// Partial specialization for std::allocator.
410  template<typename _Tp>
411    struct allocator_traits<allocator<_Tp>>
412    {
413      /// The allocator type
414      using allocator_type = allocator<_Tp>;
415
416      /// The allocated type
417      using value_type = _Tp;
418
419      /// The allocator's pointer type.
420      using pointer = _Tp*;
421
422      /// The allocator's const pointer type.
423      using const_pointer = const _Tp*;
424
425      /// The allocator's void pointer type.
426      using void_pointer = void*;
427
428      /// The allocator's const void pointer type.
429      using const_void_pointer = const void*;
430
431      /// The allocator's difference type
432      using difference_type = std::ptrdiff_t;
433
434      /// The allocator's size type
435      using size_type = std::size_t;
436
437      /// How the allocator is propagated on copy assignment
438      using propagate_on_container_copy_assignment = false_type;
439
440      /// How the allocator is propagated on move assignment
441      using propagate_on_container_move_assignment = true_type;
442
443      /// How the allocator is propagated on swap
444      using propagate_on_container_swap = false_type;
445
446      /// Whether all instances of the allocator type compare equal.
447      using is_always_equal = true_type;
448
449      template<typename _Up>
450	using rebind_alloc = allocator<_Up>;
451
452      template<typename _Up>
453	using rebind_traits = allocator_traits<allocator<_Up>>;
454
455      /**
456       *  @brief  Allocate memory.
457       *  @param  __a  An allocator.
458       *  @param  __n  The number of objects to allocate space for.
459       *
460       *  Calls @c a.allocate(n)
461      */
462      _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
463      allocate(allocator_type& __a, size_type __n)
464      { return __a.allocate(__n); }
465
466      /**
467       *  @brief  Allocate memory.
468       *  @param  __a  An allocator.
469       *  @param  __n  The number of objects to allocate space for.
470       *  @param  __hint Aid to locality.
471       *  @return Memory of suitable size and alignment for @a n objects
472       *          of type @c value_type
473       *
474       *  Returns <tt> a.allocate(n, hint) </tt>
475      */
476      _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
477      allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
478      {
479#if __cplusplus <= 201703L
480	return __a.allocate(__n, __hint);
481#else
482	return __a.allocate(__n);
483#endif
484      }
485
486      /**
487       *  @brief  Deallocate memory.
488       *  @param  __a  An allocator.
489       *  @param  __p  Pointer to the memory to deallocate.
490       *  @param  __n  The number of objects space was allocated for.
491       *
492       *  Calls <tt> a.deallocate(p, n) </tt>
493      */
494      static _GLIBCXX20_CONSTEXPR void
495      deallocate(allocator_type& __a, pointer __p, size_type __n)
496      { __a.deallocate(__p, __n); }
497
498      /**
499       *  @brief  Construct an object of type `_Up`
500       *  @param  __a  An allocator.
501       *  @param  __p  Pointer to memory of suitable size and alignment for
502       *	       an object of type `_Up`.
503       *  @param  __args Constructor arguments.
504       *
505       *  Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
506       *  in C++11, C++14 and C++17. Changed in C++20 to call
507       *  `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
508      */
509      template<typename _Up, typename... _Args>
510	static _GLIBCXX20_CONSTEXPR void
511	construct(allocator_type& __a __attribute__((__unused__)), _Up* __p,
512		  _Args&&... __args)
513	noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
514	{
515#if __cplusplus <= 201703L
516	  __a.construct(__p, std::forward<_Args>(__args)...);
517#else
518	  std::construct_at(__p, std::forward<_Args>(__args)...);
519#endif
520	}
521
522      /**
523       *  @brief  Destroy an object of type @a _Up
524       *  @param  __a  An allocator.
525       *  @param  __p  Pointer to the object to destroy
526       *
527       *  Calls @c __a.destroy(__p).
528      */
529      template<typename _Up>
530	static _GLIBCXX20_CONSTEXPR void
531	destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p)
532	noexcept(is_nothrow_destructible<_Up>::value)
533	{
534#if __cplusplus <= 201703L
535	  __a.destroy(__p);
536#else
537	  std::destroy_at(__p);
538#endif
539	}
540
541      /**
542       *  @brief  The maximum supported allocation size
543       *  @param  __a  An allocator.
544       *  @return @c __a.max_size()
545      */
546      static _GLIBCXX20_CONSTEXPR size_type
547      max_size(const allocator_type& __a __attribute__((__unused__))) noexcept
548      {
549#if __cplusplus <= 201703L
550	return __a.max_size();
551#else
552	return size_t(-1) / sizeof(value_type);
553#endif
554      }
555
556      /**
557       *  @brief  Obtain an allocator to use when copying a container.
558       *  @param  __rhs  An allocator.
559       *  @return @c __rhs
560      */
561      static _GLIBCXX20_CONSTEXPR allocator_type
562      select_on_container_copy_construction(const allocator_type& __rhs)
563      { return __rhs; }
564    };
565
566  /// Explicit specialization for std::allocator<void>.
567  template<>
568    struct allocator_traits<allocator<void>>
569    {
570      /// The allocator type
571      using allocator_type = allocator<void>;
572
573      /// The allocated type
574      using value_type = void;
575
576      /// The allocator's pointer type.
577      using pointer = void*;
578
579      /// The allocator's const pointer type.
580      using const_pointer = const void*;
581
582      /// The allocator's void pointer type.
583      using void_pointer = void*;
584
585      /// The allocator's const void pointer type.
586      using const_void_pointer = const void*;
587
588      /// The allocator's difference type
589      using difference_type = std::ptrdiff_t;
590
591      /// The allocator's size type
592      using size_type = std::size_t;
593
594      /// How the allocator is propagated on copy assignment
595      using propagate_on_container_copy_assignment = false_type;
596
597      /// How the allocator is propagated on move assignment
598      using propagate_on_container_move_assignment = true_type;
599
600      /// How the allocator is propagated on swap
601      using propagate_on_container_swap = false_type;
602
603      /// Whether all instances of the allocator type compare equal.
604      using is_always_equal = true_type;
605
606      template<typename _Up>
607	using rebind_alloc = allocator<_Up>;
608
609      template<typename _Up>
610	using rebind_traits = allocator_traits<allocator<_Up>>;
611
612      /// allocate is ill-formed for allocator<void>
613      static void*
614      allocate(allocator_type&, size_type, const void* = nullptr) = delete;
615
616      /// deallocate is ill-formed for allocator<void>
617      static void
618      deallocate(allocator_type&, void*, size_type) = delete;
619
620      /**
621       *  @brief  Construct an object of type `_Up`
622       *  @param  __a  An allocator.
623       *  @param  __p  Pointer to memory of suitable size and alignment for
624       *	       an object of type `_Up`.
625       *  @param  __args Constructor arguments.
626       *
627       *  Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
628       *  in C++11, C++14 and C++17. Changed in C++20 to call
629       *  `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
630      */
631      template<typename _Up, typename... _Args>
632	static _GLIBCXX20_CONSTEXPR void
633	construct(allocator_type&, _Up* __p, _Args&&... __args)
634	noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
635	{ std::_Construct(__p, std::forward<_Args>(__args)...); }
636
637      /**
638       *  @brief  Destroy an object of type `_Up`
639       *  @param  __a  An allocator.
640       *  @param  __p  Pointer to the object to destroy
641       *
642       *  Invokes the destructor for `*__p`.
643      */
644      template<typename _Up>
645	static _GLIBCXX20_CONSTEXPR void
646	destroy(allocator_type&, _Up* __p)
647	noexcept(is_nothrow_destructible<_Up>::value)
648	{ std::_Destroy(__p); }
649
650      /// max_size is ill-formed for allocator<void>
651      static size_type
652      max_size(const allocator_type&) = delete;
653
654      /**
655       *  @brief  Obtain an allocator to use when copying a container.
656       *  @param  __rhs  An allocator.
657       *  @return `__rhs`
658      */
659      static _GLIBCXX20_CONSTEXPR allocator_type
660      select_on_container_copy_construction(const allocator_type& __rhs)
661      { return __rhs; }
662    };
663
664#if __cplusplus < 201703L
665  template<typename _Alloc>
666    inline void
667    __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
668    { __one = __two; }
669
670  template<typename _Alloc>
671    inline void
672    __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
673    { }
674#endif
675
676  template<typename _Alloc>
677    _GLIBCXX14_CONSTEXPR inline void
678    __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
679    {
680      typedef allocator_traits<_Alloc> __traits;
681      typedef typename __traits::propagate_on_container_copy_assignment __pocca;
682#if __cplusplus >= 201703L
683      if constexpr (__pocca::value)
684	__one = __two;
685#else
686      __do_alloc_on_copy(__one, __two, __pocca());
687#endif
688    }
689
690  template<typename _Alloc>
691    constexpr _Alloc
692    __alloc_on_copy(const _Alloc& __a)
693    {
694      typedef allocator_traits<_Alloc> __traits;
695      return __traits::select_on_container_copy_construction(__a);
696    }
697
698#if __cplusplus < 201703L
699  template<typename _Alloc>
700    inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
701    { __one = std::move(__two); }
702
703  template<typename _Alloc>
704    inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
705    { }
706#endif
707
708  template<typename _Alloc>
709    _GLIBCXX14_CONSTEXPR inline void
710    __alloc_on_move(_Alloc& __one, _Alloc& __two)
711    {
712      typedef allocator_traits<_Alloc> __traits;
713      typedef typename __traits::propagate_on_container_move_assignment __pocma;
714#if __cplusplus >= 201703L
715      if constexpr (__pocma::value)
716	__one = std::move(__two);
717#else
718      __do_alloc_on_move(__one, __two, __pocma());
719#endif
720    }
721
722#if __cplusplus < 201703L
723  template<typename _Alloc>
724    inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
725    {
726      using std::swap;
727      swap(__one, __two);
728    }
729
730  template<typename _Alloc>
731    inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
732    { }
733#endif
734
735  template<typename _Alloc>
736    _GLIBCXX14_CONSTEXPR inline void
737    __alloc_on_swap(_Alloc& __one, _Alloc& __two)
738    {
739      typedef allocator_traits<_Alloc> __traits;
740      typedef typename __traits::propagate_on_container_swap __pocs;
741#if __cplusplus >= 201703L
742      if constexpr (__pocs::value)
743	{
744	  using std::swap;
745	  swap(__one, __two);
746	}
747#else
748      __do_alloc_on_swap(__one, __two, __pocs());
749#endif
750    }
751
752  template<typename _Alloc, typename _Tp,
753	   typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
754	   typename = void>
755    struct __is_alloc_insertable_impl
756    : false_type
757    { };
758
759  template<typename _Alloc, typename _Tp, typename _ValueT>
760    struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
761      __void_t<decltype(allocator_traits<_Alloc>::construct(
762		   std::declval<_Alloc&>(), std::declval<_ValueT*>(),
763		   std::declval<_Tp>()))>>
764    : true_type
765    { };
766
767  // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
768  // (might be wrong if _Alloc::construct exists but is not constrained,
769  // i.e. actually trying to use it would still be invalid. Use with caution.)
770  template<typename _Alloc>
771    struct __is_copy_insertable
772    : __is_alloc_insertable_impl<_Alloc,
773				 typename _Alloc::value_type const&>::type
774    { };
775
776  // std::allocator<_Tp> just requires CopyConstructible
777  template<typename _Tp>
778    struct __is_copy_insertable<allocator<_Tp>>
779    : is_copy_constructible<_Tp>
780    { };
781
782  // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
783  // (might be wrong if _Alloc::construct exists but is not constrained,
784  // i.e. actually trying to use it would still be invalid. Use with caution.)
785  template<typename _Alloc>
786    struct __is_move_insertable
787    : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
788    { };
789
790  // std::allocator<_Tp> just requires MoveConstructible
791  template<typename _Tp>
792    struct __is_move_insertable<allocator<_Tp>>
793    : is_move_constructible<_Tp>
794    { };
795
796  // Trait to detect Allocator-like types.
797  template<typename _Alloc, typename = void>
798    struct __is_allocator : false_type { };
799
800  template<typename _Alloc>
801    struct __is_allocator<_Alloc,
802      __void_t<typename _Alloc::value_type,
803	       decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
804    : true_type { };
805
806  template<typename _Alloc>
807    using _RequireAllocator
808      = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
809
810  template<typename _Alloc>
811    using _RequireNotAllocator
812      = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
813
814#if __cpp_concepts >= 201907L
815  template<typename _Alloc>
816    concept __allocator_like = requires (_Alloc& __a) {
817      typename _Alloc::value_type;
818      __a.deallocate(__a.allocate(1u), 1u);
819    };
820#endif
821#endif // C++11
822
823  /**
824   * Destroy a range of objects using the supplied allocator.  For
825   * non-default allocators we do not optimize away invocation of
826   * destroy() even if _Tp has a trivial destructor.
827   */
828
829  template<typename _ForwardIterator, typename _Allocator>
830    _GLIBCXX20_CONSTEXPR
831    void
832    _Destroy(_ForwardIterator __first, _ForwardIterator __last,
833	     _Allocator& __alloc)
834    {
835      for (; __first != __last; ++__first)
836#if __cplusplus < 201103L
837	__alloc.destroy(std::__addressof(*__first));
838#else
839	allocator_traits<_Allocator>::destroy(__alloc,
840					      std::__addressof(*__first));
841#endif
842    }
843
844  template<typename _ForwardIterator, typename _Tp>
845    _GLIBCXX20_CONSTEXPR
846    inline void
847    _Destroy(_ForwardIterator __first, _ForwardIterator __last,
848	     allocator<_Tp>&)
849    {
850      _Destroy(__first, __last);
851    }
852
853_GLIBCXX_END_NAMESPACE_VERSION
854} // namespace std
855#endif // _ALLOC_TRAITS_H
856