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