xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/bits/alloc_traits.h (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj // Allocator traits -*- C++ -*-
238fd1498Szrj 
338fd1498Szrj // Copyright (C) 2011-2018 Free Software Foundation, Inc.
438fd1498Szrj //
538fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
638fd1498Szrj // software; you can redistribute it and/or modify it under the
738fd1498Szrj // terms of the GNU General Public License as published by the
838fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj // any later version.
1038fd1498Szrj 
1138fd1498Szrj // This library is distributed in the hope that it will be useful,
1238fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1438fd1498Szrj // GNU General Public License for more details.
1538fd1498Szrj 
1638fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
1738fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
1838fd1498Szrj // 3.1, as published by the Free Software Foundation.
1938fd1498Szrj 
2038fd1498Szrj // You should have received a copy of the GNU General Public License and
2138fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
2238fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2338fd1498Szrj // <http://www.gnu.org/licenses/>.
2438fd1498Szrj 
2538fd1498Szrj /** @file bits/alloc_traits.h
2638fd1498Szrj  *  This is an internal header file, included by other library headers.
2738fd1498Szrj  *  Do not attempt to use it directly. @headername{memory}
2838fd1498Szrj  */
2938fd1498Szrj 
3038fd1498Szrj #ifndef _ALLOC_TRAITS_H
3138fd1498Szrj #define _ALLOC_TRAITS_H 1
3238fd1498Szrj 
3338fd1498Szrj #if __cplusplus >= 201103L
3438fd1498Szrj 
3538fd1498Szrj #include <bits/memoryfwd.h>
3638fd1498Szrj #include <bits/ptr_traits.h>
3738fd1498Szrj #include <ext/numeric_traits.h>
3838fd1498Szrj 
3938fd1498Szrj #define __cpp_lib_allocator_traits_is_always_equal 201411
4038fd1498Szrj 
_GLIBCXX_VISIBILITY(default)4138fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
4238fd1498Szrj {
4338fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
4438fd1498Szrj 
4538fd1498Szrj   struct __allocator_traits_base
4638fd1498Szrj   {
4738fd1498Szrj     template<typename _Tp, typename _Up, typename = void>
4838fd1498Szrj       struct __rebind : __replace_first_arg<_Tp, _Up> { };
4938fd1498Szrj 
5038fd1498Szrj     template<typename _Tp, typename _Up>
5138fd1498Szrj       struct __rebind<_Tp, _Up,
5238fd1498Szrj 		      __void_t<typename _Tp::template rebind<_Up>::other>>
5338fd1498Szrj       { using type = typename _Tp::template rebind<_Up>::other; };
5438fd1498Szrj 
5538fd1498Szrj   protected:
5638fd1498Szrj     template<typename _Tp>
5738fd1498Szrj       using __pointer = typename _Tp::pointer;
5838fd1498Szrj     template<typename _Tp>
5938fd1498Szrj       using __c_pointer = typename _Tp::const_pointer;
6038fd1498Szrj     template<typename _Tp>
6138fd1498Szrj       using __v_pointer = typename _Tp::void_pointer;
6238fd1498Szrj     template<typename _Tp>
6338fd1498Szrj       using __cv_pointer = typename _Tp::const_void_pointer;
6438fd1498Szrj     template<typename _Tp>
6538fd1498Szrj       using __pocca = typename _Tp::propagate_on_container_copy_assignment;
6638fd1498Szrj     template<typename _Tp>
6738fd1498Szrj       using __pocma = typename _Tp::propagate_on_container_move_assignment;
6838fd1498Szrj     template<typename _Tp>
6938fd1498Szrj       using __pocs = typename _Tp::propagate_on_container_swap;
7038fd1498Szrj     template<typename _Tp>
7138fd1498Szrj       using __equal = typename _Tp::is_always_equal;
7238fd1498Szrj   };
7338fd1498Szrj 
7438fd1498Szrj   template<typename _Alloc, typename _Up>
7538fd1498Szrj     using __alloc_rebind
7638fd1498Szrj       = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
7738fd1498Szrj 
7838fd1498Szrj   /**
7938fd1498Szrj    * @brief  Uniform interface to all allocator types.
8038fd1498Szrj    * @ingroup allocators
8138fd1498Szrj   */
8238fd1498Szrj   template<typename _Alloc>
8338fd1498Szrj     struct allocator_traits : __allocator_traits_base
8438fd1498Szrj     {
8538fd1498Szrj       /// The allocator type
8638fd1498Szrj       typedef _Alloc allocator_type;
8738fd1498Szrj       /// The allocated type
8838fd1498Szrj       typedef typename _Alloc::value_type value_type;
8938fd1498Szrj 
9038fd1498Szrj       /**
9138fd1498Szrj        * @brief   The allocator's pointer type.
9238fd1498Szrj        *
9338fd1498Szrj        * @c Alloc::pointer if that type exists, otherwise @c value_type*
9438fd1498Szrj       */
9538fd1498Szrj       using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
9638fd1498Szrj 
9738fd1498Szrj     private:
9838fd1498Szrj       // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
9938fd1498Szrj       template<template<typename> class _Func, typename _Tp, typename = void>
10038fd1498Szrj 	struct _Ptr
10138fd1498Szrj 	{
10238fd1498Szrj 	  using type = typename pointer_traits<pointer>::template rebind<_Tp>;
10338fd1498Szrj 	};
10438fd1498Szrj 
10538fd1498Szrj       template<template<typename> class _Func, typename _Tp>
10638fd1498Szrj 	struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
10738fd1498Szrj 	{
10838fd1498Szrj 	  using type = _Func<_Alloc>;
10938fd1498Szrj 	};
11038fd1498Szrj 
11138fd1498Szrj       // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
11238fd1498Szrj       template<typename _A2, typename _PtrT, typename = void>
11338fd1498Szrj 	struct _Diff
11438fd1498Szrj 	{ using type = typename pointer_traits<_PtrT>::difference_type; };
11538fd1498Szrj 
11638fd1498Szrj       template<typename _A2, typename _PtrT>
11738fd1498Szrj 	struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
11838fd1498Szrj 	{ using type = typename _A2::difference_type; };
11938fd1498Szrj 
12038fd1498Szrj       // Select _A2::size_type or make_unsigned<_DiffT>::type
12138fd1498Szrj       template<typename _A2, typename _DiffT, typename = void>
12238fd1498Szrj 	struct _Size : make_unsigned<_DiffT> { };
12338fd1498Szrj 
12438fd1498Szrj       template<typename _A2, typename _DiffT>
12538fd1498Szrj 	struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
12638fd1498Szrj 	{ using type = typename _A2::size_type; };
12738fd1498Szrj 
12838fd1498Szrj     public:
12938fd1498Szrj       /**
13038fd1498Szrj        * @brief   The allocator's const pointer type.
13138fd1498Szrj        *
13238fd1498Szrj        * @c Alloc::const_pointer if that type exists, otherwise
13338fd1498Szrj        * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
13438fd1498Szrj       */
13538fd1498Szrj       using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
13638fd1498Szrj 
13738fd1498Szrj       /**
13838fd1498Szrj        * @brief   The allocator's void pointer type.
13938fd1498Szrj        *
14038fd1498Szrj        * @c Alloc::void_pointer if that type exists, otherwise
14138fd1498Szrj        * <tt> pointer_traits<pointer>::rebind<void> </tt>
14238fd1498Szrj       */
14338fd1498Szrj       using void_pointer = typename _Ptr<__v_pointer, void>::type;
14438fd1498Szrj 
14538fd1498Szrj       /**
14638fd1498Szrj        * @brief   The allocator's const void pointer type.
14738fd1498Szrj        *
14838fd1498Szrj        * @c Alloc::const_void_pointer if that type exists, otherwise
14938fd1498Szrj        * <tt> pointer_traits<pointer>::rebind<const void> </tt>
15038fd1498Szrj       */
15138fd1498Szrj       using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
15238fd1498Szrj 
15338fd1498Szrj       /**
15438fd1498Szrj        * @brief   The allocator's difference type
15538fd1498Szrj        *
15638fd1498Szrj        * @c Alloc::difference_type if that type exists, otherwise
15738fd1498Szrj        * <tt> pointer_traits<pointer>::difference_type </tt>
15838fd1498Szrj       */
15938fd1498Szrj       using difference_type = typename _Diff<_Alloc, pointer>::type;
16038fd1498Szrj 
16138fd1498Szrj       /**
16238fd1498Szrj        * @brief   The allocator's size type
16338fd1498Szrj        *
16438fd1498Szrj        * @c Alloc::size_type if that type exists, otherwise
16538fd1498Szrj        * <tt> make_unsigned<difference_type>::type </tt>
16638fd1498Szrj       */
16738fd1498Szrj       using size_type = typename _Size<_Alloc, difference_type>::type;
16838fd1498Szrj 
16938fd1498Szrj       /**
17038fd1498Szrj        * @brief   How the allocator is propagated on copy assignment
17138fd1498Szrj        *
17238fd1498Szrj        * @c Alloc::propagate_on_container_copy_assignment if that type exists,
17338fd1498Szrj        * otherwise @c false_type
17438fd1498Szrj       */
17538fd1498Szrj       using propagate_on_container_copy_assignment
17638fd1498Szrj 	= __detected_or_t<false_type, __pocca, _Alloc>;
17738fd1498Szrj 
17838fd1498Szrj       /**
17938fd1498Szrj        * @brief   How the allocator is propagated on move assignment
18038fd1498Szrj        *
18138fd1498Szrj        * @c Alloc::propagate_on_container_move_assignment if that type exists,
18238fd1498Szrj        * otherwise @c false_type
18338fd1498Szrj       */
18438fd1498Szrj       using propagate_on_container_move_assignment
18538fd1498Szrj 	= __detected_or_t<false_type, __pocma, _Alloc>;
18638fd1498Szrj 
18738fd1498Szrj       /**
18838fd1498Szrj        * @brief   How the allocator is propagated on swap
18938fd1498Szrj        *
19038fd1498Szrj        * @c Alloc::propagate_on_container_swap if that type exists,
19138fd1498Szrj        * otherwise @c false_type
19238fd1498Szrj       */
19338fd1498Szrj       using propagate_on_container_swap
19438fd1498Szrj 	= __detected_or_t<false_type, __pocs, _Alloc>;
19538fd1498Szrj 
19638fd1498Szrj       /**
19738fd1498Szrj        * @brief   Whether all instances of the allocator type compare equal.
19838fd1498Szrj        *
19938fd1498Szrj        * @c Alloc::is_always_equal if that type exists,
20038fd1498Szrj        * otherwise @c is_empty<Alloc>::type
20138fd1498Szrj       */
20238fd1498Szrj       using is_always_equal
20338fd1498Szrj 	= __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
20438fd1498Szrj 
20538fd1498Szrj       template<typename _Tp>
20638fd1498Szrj 	using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
20738fd1498Szrj       template<typename _Tp>
20838fd1498Szrj 	using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
20938fd1498Szrj 
21038fd1498Szrj     private:
21138fd1498Szrj       template<typename _Alloc2>
21238fd1498Szrj 	static auto
21338fd1498Szrj 	_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
21438fd1498Szrj 	-> decltype(__a.allocate(__n, __hint))
21538fd1498Szrj 	{ return __a.allocate(__n, __hint); }
21638fd1498Szrj 
21738fd1498Szrj       template<typename _Alloc2>
21838fd1498Szrj 	static pointer
21938fd1498Szrj 	_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
22038fd1498Szrj 	{ return __a.allocate(__n); }
22138fd1498Szrj 
22238fd1498Szrj       template<typename _Tp, typename... _Args>
22338fd1498Szrj 	struct __construct_helper
22438fd1498Szrj 	{
22538fd1498Szrj 	  template<typename _Alloc2,
22638fd1498Szrj 	    typename = decltype(std::declval<_Alloc2*>()->construct(
22738fd1498Szrj 		  std::declval<_Tp*>(), std::declval<_Args>()...))>
22838fd1498Szrj 	    static true_type __test(int);
22938fd1498Szrj 
23038fd1498Szrj 	  template<typename>
23138fd1498Szrj 	    static false_type __test(...);
23238fd1498Szrj 
23338fd1498Szrj 	  using type = decltype(__test<_Alloc>(0));
23438fd1498Szrj 	};
23538fd1498Szrj 
23638fd1498Szrj       template<typename _Tp, typename... _Args>
23738fd1498Szrj 	using __has_construct
23838fd1498Szrj 	  = typename __construct_helper<_Tp, _Args...>::type;
23938fd1498Szrj 
24038fd1498Szrj       template<typename _Tp, typename... _Args>
24138fd1498Szrj 	static _Require<__has_construct<_Tp, _Args...>>
24238fd1498Szrj 	_S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
24338fd1498Szrj 	{ __a.construct(__p, std::forward<_Args>(__args)...); }
24438fd1498Szrj 
24538fd1498Szrj       template<typename _Tp, typename... _Args>
24638fd1498Szrj 	static
24738fd1498Szrj 	_Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
24838fd1498Szrj 			       is_constructible<_Tp, _Args...>>>
24938fd1498Szrj 	_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
25038fd1498Szrj 	{ ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
25138fd1498Szrj 
25238fd1498Szrj       template<typename _Alloc2, typename _Tp>
25338fd1498Szrj 	static auto
25438fd1498Szrj 	_S_destroy(_Alloc2& __a, _Tp* __p, int)
25538fd1498Szrj 	-> decltype(__a.destroy(__p))
25638fd1498Szrj 	{ __a.destroy(__p); }
25738fd1498Szrj 
25838fd1498Szrj       template<typename _Alloc2, typename _Tp>
25938fd1498Szrj 	static void
26038fd1498Szrj 	_S_destroy(_Alloc2&, _Tp* __p, ...)
26138fd1498Szrj 	{ __p->~_Tp(); }
26238fd1498Szrj 
26338fd1498Szrj       template<typename _Alloc2>
26438fd1498Szrj 	static auto
26538fd1498Szrj 	_S_max_size(_Alloc2& __a, int)
26638fd1498Szrj 	-> decltype(__a.max_size())
26738fd1498Szrj 	{ return __a.max_size(); }
26838fd1498Szrj 
26938fd1498Szrj       template<typename _Alloc2>
27038fd1498Szrj 	static size_type
27138fd1498Szrj 	_S_max_size(_Alloc2&, ...)
27238fd1498Szrj 	{
27338fd1498Szrj 	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
27438fd1498Szrj 	  // 2466. allocator_traits::max_size() default behavior is incorrect
27538fd1498Szrj 	  return __gnu_cxx::__numeric_traits<size_type>::__max
27638fd1498Szrj 	    / sizeof(value_type);
27738fd1498Szrj 	}
27838fd1498Szrj 
27938fd1498Szrj       template<typename _Alloc2>
28038fd1498Szrj 	static auto
28138fd1498Szrj 	_S_select(_Alloc2& __a, int)
28238fd1498Szrj 	-> decltype(__a.select_on_container_copy_construction())
28338fd1498Szrj 	{ return __a.select_on_container_copy_construction(); }
28438fd1498Szrj 
28538fd1498Szrj       template<typename _Alloc2>
28638fd1498Szrj 	static _Alloc2
28738fd1498Szrj 	_S_select(_Alloc2& __a, ...)
28838fd1498Szrj 	{ return __a; }
28938fd1498Szrj 
29038fd1498Szrj     public:
29138fd1498Szrj 
29238fd1498Szrj       /**
29338fd1498Szrj        *  @brief  Allocate memory.
29438fd1498Szrj        *  @param  __a  An allocator.
29538fd1498Szrj        *  @param  __n  The number of objects to allocate space for.
29638fd1498Szrj        *
29738fd1498Szrj        *  Calls @c a.allocate(n)
29838fd1498Szrj       */
29938fd1498Szrj       static pointer
30038fd1498Szrj       allocate(_Alloc& __a, size_type __n)
30138fd1498Szrj       { return __a.allocate(__n); }
30238fd1498Szrj 
30338fd1498Szrj       /**
30438fd1498Szrj        *  @brief  Allocate memory.
30538fd1498Szrj        *  @param  __a  An allocator.
30638fd1498Szrj        *  @param  __n  The number of objects to allocate space for.
30738fd1498Szrj        *  @param  __hint Aid to locality.
30838fd1498Szrj        *  @return Memory of suitable size and alignment for @a n objects
30938fd1498Szrj        *          of type @c value_type
31038fd1498Szrj        *
31138fd1498Szrj        *  Returns <tt> a.allocate(n, hint) </tt> if that expression is
31238fd1498Szrj        *  well-formed, otherwise returns @c a.allocate(n)
31338fd1498Szrj       */
31438fd1498Szrj       static pointer
31538fd1498Szrj       allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
31638fd1498Szrj       { return _S_allocate(__a, __n, __hint, 0); }
31738fd1498Szrj 
31838fd1498Szrj       /**
31938fd1498Szrj        *  @brief  Deallocate memory.
32038fd1498Szrj        *  @param  __a  An allocator.
32138fd1498Szrj        *  @param  __p  Pointer to the memory to deallocate.
32238fd1498Szrj        *  @param  __n  The number of objects space was allocated for.
32338fd1498Szrj        *
32438fd1498Szrj        *  Calls <tt> a.deallocate(p, n) </tt>
32538fd1498Szrj       */
32638fd1498Szrj       static void
32738fd1498Szrj       deallocate(_Alloc& __a, pointer __p, size_type __n)
32838fd1498Szrj       { __a.deallocate(__p, __n); }
32938fd1498Szrj 
33038fd1498Szrj       /**
33138fd1498Szrj        *  @brief  Construct an object of type @a _Tp
33238fd1498Szrj        *  @param  __a  An allocator.
33338fd1498Szrj        *  @param  __p  Pointer to memory of suitable size and alignment for Tp
33438fd1498Szrj        *  @param  __args Constructor arguments.
33538fd1498Szrj        *
33638fd1498Szrj        *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
33738fd1498Szrj        *  if that expression is well-formed, otherwise uses placement-new
33838fd1498Szrj        *  to construct an object of type @a _Tp at location @a __p from the
33938fd1498Szrj        *  arguments @a __args...
34038fd1498Szrj       */
34138fd1498Szrj       template<typename _Tp, typename... _Args>
34238fd1498Szrj 	static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
34338fd1498Szrj 	-> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
34438fd1498Szrj 	{ _S_construct(__a, __p, std::forward<_Args>(__args)...); }
34538fd1498Szrj 
34638fd1498Szrj       /**
34738fd1498Szrj        *  @brief  Destroy an object of type @a _Tp
34838fd1498Szrj        *  @param  __a  An allocator.
34938fd1498Szrj        *  @param  __p  Pointer to the object to destroy
35038fd1498Szrj        *
35138fd1498Szrj        *  Calls @c __a.destroy(__p) if that expression is well-formed,
35238fd1498Szrj        *  otherwise calls @c __p->~_Tp()
35338fd1498Szrj       */
35438fd1498Szrj       template<typename _Tp>
35538fd1498Szrj 	static void destroy(_Alloc& __a, _Tp* __p)
35638fd1498Szrj 	{ _S_destroy(__a, __p, 0); }
35738fd1498Szrj 
35838fd1498Szrj       /**
35938fd1498Szrj        *  @brief  The maximum supported allocation size
36038fd1498Szrj        *  @param  __a  An allocator.
36138fd1498Szrj        *  @return @c __a.max_size() or @c numeric_limits<size_type>::max()
36238fd1498Szrj        *
36338fd1498Szrj        *  Returns @c __a.max_size() if that expression is well-formed,
36438fd1498Szrj        *  otherwise returns @c numeric_limits<size_type>::max()
36538fd1498Szrj       */
36638fd1498Szrj       static size_type max_size(const _Alloc& __a) noexcept
36738fd1498Szrj       { return _S_max_size(__a, 0); }
36838fd1498Szrj 
36938fd1498Szrj       /**
37038fd1498Szrj        *  @brief  Obtain an allocator to use when copying a container.
37138fd1498Szrj        *  @param  __rhs  An allocator.
37238fd1498Szrj        *  @return @c __rhs.select_on_container_copy_construction() or @a __rhs
37338fd1498Szrj        *
37438fd1498Szrj        *  Returns @c __rhs.select_on_container_copy_construction() if that
37538fd1498Szrj        *  expression is well-formed, otherwise returns @a __rhs
37638fd1498Szrj       */
37738fd1498Szrj       static _Alloc
37838fd1498Szrj       select_on_container_copy_construction(const _Alloc& __rhs)
37938fd1498Szrj       { return _S_select(__rhs, 0); }
38038fd1498Szrj     };
38138fd1498Szrj 
38238fd1498Szrj   /// Partial specialization for std::allocator.
38338fd1498Szrj   template<typename _Tp>
38438fd1498Szrj     struct allocator_traits<allocator<_Tp>>
38538fd1498Szrj     {
38638fd1498Szrj       /// The allocator type
38738fd1498Szrj       using allocator_type = allocator<_Tp>;
38838fd1498Szrj       /// The allocated type
38938fd1498Szrj       using value_type = _Tp;
39038fd1498Szrj 
39138fd1498Szrj       /// The allocator's pointer type.
39238fd1498Szrj       using pointer = _Tp*;
39338fd1498Szrj 
39438fd1498Szrj       /// The allocator's const pointer type.
39538fd1498Szrj       using const_pointer = const _Tp*;
39638fd1498Szrj 
39738fd1498Szrj       /// The allocator's void pointer type.
39838fd1498Szrj       using void_pointer = void*;
39938fd1498Szrj 
40038fd1498Szrj       /// The allocator's const void pointer type.
40138fd1498Szrj       using const_void_pointer = const void*;
40238fd1498Szrj 
40338fd1498Szrj       /// The allocator's difference type
40438fd1498Szrj       using difference_type = std::ptrdiff_t;
40538fd1498Szrj 
40638fd1498Szrj       /// The allocator's size type
40738fd1498Szrj       using size_type = std::size_t;
40838fd1498Szrj 
40938fd1498Szrj       /// How the allocator is propagated on copy assignment
41038fd1498Szrj       using propagate_on_container_copy_assignment = false_type;
41138fd1498Szrj 
41238fd1498Szrj       /// How the allocator is propagated on move assignment
41338fd1498Szrj       using propagate_on_container_move_assignment = true_type;
41438fd1498Szrj 
41538fd1498Szrj       /// How the allocator is propagated on swap
41638fd1498Szrj       using propagate_on_container_swap = false_type;
41738fd1498Szrj 
41838fd1498Szrj       /// Whether all instances of the allocator type compare equal.
41938fd1498Szrj       using is_always_equal = true_type;
42038fd1498Szrj 
42138fd1498Szrj       template<typename _Up>
42238fd1498Szrj 	using rebind_alloc = allocator<_Up>;
42338fd1498Szrj 
42438fd1498Szrj       template<typename _Up>
42538fd1498Szrj 	using rebind_traits = allocator_traits<allocator<_Up>>;
42638fd1498Szrj 
42738fd1498Szrj       /**
42838fd1498Szrj        *  @brief  Allocate memory.
42938fd1498Szrj        *  @param  __a  An allocator.
43038fd1498Szrj        *  @param  __n  The number of objects to allocate space for.
43138fd1498Szrj        *
43238fd1498Szrj        *  Calls @c a.allocate(n)
43338fd1498Szrj       */
43438fd1498Szrj       static pointer
43538fd1498Szrj       allocate(allocator_type& __a, size_type __n)
43638fd1498Szrj       { return __a.allocate(__n); }
43738fd1498Szrj 
43838fd1498Szrj       /**
43938fd1498Szrj        *  @brief  Allocate memory.
44038fd1498Szrj        *  @param  __a  An allocator.
44138fd1498Szrj        *  @param  __n  The number of objects to allocate space for.
44238fd1498Szrj        *  @param  __hint Aid to locality.
44338fd1498Szrj        *  @return Memory of suitable size and alignment for @a n objects
44438fd1498Szrj        *          of type @c value_type
44538fd1498Szrj        *
44638fd1498Szrj        *  Returns <tt> a.allocate(n, hint) </tt>
44738fd1498Szrj       */
44838fd1498Szrj       static pointer
44938fd1498Szrj       allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
45038fd1498Szrj       { return __a.allocate(__n, __hint); }
45138fd1498Szrj 
45238fd1498Szrj       /**
45338fd1498Szrj        *  @brief  Deallocate memory.
45438fd1498Szrj        *  @param  __a  An allocator.
45538fd1498Szrj        *  @param  __p  Pointer to the memory to deallocate.
45638fd1498Szrj        *  @param  __n  The number of objects space was allocated for.
45738fd1498Szrj        *
45838fd1498Szrj        *  Calls <tt> a.deallocate(p, n) </tt>
45938fd1498Szrj       */
46038fd1498Szrj       static void
46138fd1498Szrj       deallocate(allocator_type& __a, pointer __p, size_type __n)
46238fd1498Szrj       { __a.deallocate(__p, __n); }
46338fd1498Szrj 
46438fd1498Szrj       /**
46538fd1498Szrj        *  @brief  Construct an object of type @a _Up
46638fd1498Szrj        *  @param  __a  An allocator.
46738fd1498Szrj        *  @param  __p  Pointer to memory of suitable size and alignment for Tp
46838fd1498Szrj        *  @param  __args Constructor arguments.
46938fd1498Szrj        *
47038fd1498Szrj        *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
47138fd1498Szrj       */
47238fd1498Szrj       template<typename _Up, typename... _Args>
47338fd1498Szrj 	static void
47438fd1498Szrj 	construct(allocator_type& __a, _Up* __p, _Args&&... __args)
47538fd1498Szrj 	{ __a.construct(__p, std::forward<_Args>(__args)...); }
47638fd1498Szrj 
47738fd1498Szrj       /**
47838fd1498Szrj        *  @brief  Destroy an object of type @a _Up
47938fd1498Szrj        *  @param  __a  An allocator.
48038fd1498Szrj        *  @param  __p  Pointer to the object to destroy
48138fd1498Szrj        *
48238fd1498Szrj        *  Calls @c __a.destroy(__p).
48338fd1498Szrj       */
48438fd1498Szrj       template<typename _Up>
48538fd1498Szrj 	static void
48638fd1498Szrj 	destroy(allocator_type& __a, _Up* __p)
48738fd1498Szrj 	{ __a.destroy(__p); }
48838fd1498Szrj 
48938fd1498Szrj       /**
49038fd1498Szrj        *  @brief  The maximum supported allocation size
49138fd1498Szrj        *  @param  __a  An allocator.
49238fd1498Szrj        *  @return @c __a.max_size()
49338fd1498Szrj       */
49438fd1498Szrj       static size_type
49538fd1498Szrj       max_size(const allocator_type& __a) noexcept
49638fd1498Szrj       { return __a.max_size(); }
49738fd1498Szrj 
49838fd1498Szrj       /**
49938fd1498Szrj        *  @brief  Obtain an allocator to use when copying a container.
50038fd1498Szrj        *  @param  __rhs  An allocator.
50138fd1498Szrj        *  @return @c __rhs
50238fd1498Szrj       */
50338fd1498Szrj       static allocator_type
50438fd1498Szrj       select_on_container_copy_construction(const allocator_type& __rhs)
50538fd1498Szrj       { return __rhs; }
50638fd1498Szrj     };
50738fd1498Szrj 
50838fd1498Szrj 
50938fd1498Szrj   template<typename _Alloc>
51038fd1498Szrj     inline void
51138fd1498Szrj     __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
51238fd1498Szrj     { __one = __two; }
51338fd1498Szrj 
51438fd1498Szrj   template<typename _Alloc>
51538fd1498Szrj     inline void
51638fd1498Szrj     __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
51738fd1498Szrj     { }
51838fd1498Szrj 
51938fd1498Szrj   template<typename _Alloc>
52038fd1498Szrj     inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
52138fd1498Szrj     {
52238fd1498Szrj       typedef allocator_traits<_Alloc> __traits;
52338fd1498Szrj       typedef typename __traits::propagate_on_container_copy_assignment __pocca;
52438fd1498Szrj       __do_alloc_on_copy(__one, __two, __pocca());
52538fd1498Szrj     }
52638fd1498Szrj 
52738fd1498Szrj   template<typename _Alloc>
52838fd1498Szrj     inline _Alloc __alloc_on_copy(const _Alloc& __a)
52938fd1498Szrj     {
53038fd1498Szrj       typedef allocator_traits<_Alloc> __traits;
53138fd1498Szrj       return __traits::select_on_container_copy_construction(__a);
53238fd1498Szrj     }
53338fd1498Szrj 
53438fd1498Szrj   template<typename _Alloc>
53538fd1498Szrj     inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
53638fd1498Szrj     { __one = std::move(__two); }
53738fd1498Szrj 
53838fd1498Szrj   template<typename _Alloc>
53938fd1498Szrj     inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
54038fd1498Szrj     { }
54138fd1498Szrj 
54238fd1498Szrj   template<typename _Alloc>
54338fd1498Szrj     inline void __alloc_on_move(_Alloc& __one, _Alloc& __two)
54438fd1498Szrj     {
54538fd1498Szrj       typedef allocator_traits<_Alloc> __traits;
54638fd1498Szrj       typedef typename __traits::propagate_on_container_move_assignment __pocma;
54738fd1498Szrj       __do_alloc_on_move(__one, __two, __pocma());
54838fd1498Szrj     }
54938fd1498Szrj 
55038fd1498Szrj   template<typename _Alloc>
55138fd1498Szrj     inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
55238fd1498Szrj     {
55338fd1498Szrj       using std::swap;
55438fd1498Szrj       swap(__one, __two);
55538fd1498Szrj     }
55638fd1498Szrj 
55738fd1498Szrj   template<typename _Alloc>
55838fd1498Szrj     inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
55938fd1498Szrj     { }
56038fd1498Szrj 
56138fd1498Szrj   template<typename _Alloc>
56238fd1498Szrj     inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two)
56338fd1498Szrj     {
56438fd1498Szrj       typedef allocator_traits<_Alloc> __traits;
56538fd1498Szrj       typedef typename __traits::propagate_on_container_swap __pocs;
56638fd1498Szrj       __do_alloc_on_swap(__one, __two, __pocs());
56738fd1498Szrj     }
56838fd1498Szrj 
56938fd1498Szrj   template<typename _Alloc>
57038fd1498Szrj     class __is_copy_insertable_impl
57138fd1498Szrj     {
57238fd1498Szrj       typedef allocator_traits<_Alloc> _Traits;
57338fd1498Szrj 
57438fd1498Szrj       template<typename _Up, typename
57538fd1498Szrj 	       = decltype(_Traits::construct(std::declval<_Alloc&>(),
57638fd1498Szrj 					     std::declval<_Up*>(),
57738fd1498Szrj 					     std::declval<const _Up&>()))>
57838fd1498Szrj 	static true_type
57938fd1498Szrj 	_M_select(int);
58038fd1498Szrj 
58138fd1498Szrj       template<typename _Up>
58238fd1498Szrj 	static false_type
58338fd1498Szrj 	_M_select(...);
58438fd1498Szrj 
58538fd1498Szrj     public:
58638fd1498Szrj       typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
58738fd1498Szrj     };
58838fd1498Szrj 
58938fd1498Szrj   // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
59038fd1498Szrj   template<typename _Alloc>
59138fd1498Szrj     struct __is_copy_insertable
59238fd1498Szrj     : __is_copy_insertable_impl<_Alloc>::type
59338fd1498Szrj     { };
59438fd1498Szrj 
59538fd1498Szrj   // std::allocator<_Tp> just requires CopyConstructible
59638fd1498Szrj   template<typename _Tp>
59738fd1498Szrj     struct __is_copy_insertable<allocator<_Tp>>
59838fd1498Szrj     : is_copy_constructible<_Tp>
59938fd1498Szrj     { };
60038fd1498Szrj 
60138fd1498Szrj   // Trait to detect Allocator-like types.
60238fd1498Szrj   template<typename _Alloc, typename = void>
60338fd1498Szrj     struct __is_allocator : false_type { };
60438fd1498Szrj 
60538fd1498Szrj   template<typename _Alloc>
60638fd1498Szrj     struct __is_allocator<_Alloc,
60738fd1498Szrj       __void_t<typename _Alloc::value_type,
60838fd1498Szrj 	       decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
60938fd1498Szrj     : true_type { };
61038fd1498Szrj 
61138fd1498Szrj   template<typename _Alloc>
61238fd1498Szrj     using _RequireAllocator
61338fd1498Szrj       = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
61438fd1498Szrj 
61538fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
61638fd1498Szrj } // namespace std
617*58e805e6Szrj #endif // C++11
618*58e805e6Szrj #endif // _ALLOC_TRAITS_H
619