11debfc3dSmrg // Allocators -*- C++ -*-
21debfc3dSmrg
3*8feb0f0bSmrg // Copyright (C) 2001-2020 Free Software Foundation, Inc.
41debfc3dSmrg //
51debfc3dSmrg // This file is part of the GNU ISO C++ Library. This library is free
61debfc3dSmrg // software; you can redistribute it and/or modify it under the
71debfc3dSmrg // terms of the GNU General Public License as published by the
81debfc3dSmrg // Free Software Foundation; either version 3, or (at your option)
91debfc3dSmrg // any later version.
101debfc3dSmrg
111debfc3dSmrg // This library is distributed in the hope that it will be useful,
121debfc3dSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
131debfc3dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
141debfc3dSmrg // GNU General Public License for more details.
151debfc3dSmrg
161debfc3dSmrg // Under Section 7 of GPL version 3, you are granted additional
171debfc3dSmrg // permissions described in the GCC Runtime Library Exception, version
181debfc3dSmrg // 3.1, as published by the Free Software Foundation.
191debfc3dSmrg
201debfc3dSmrg // You should have received a copy of the GNU General Public License and
211debfc3dSmrg // a copy of the GCC Runtime Library Exception along with this program;
221debfc3dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
231debfc3dSmrg // <http://www.gnu.org/licenses/>.
241debfc3dSmrg
251debfc3dSmrg /*
261debfc3dSmrg * Copyright (c) 1996-1997
271debfc3dSmrg * Silicon Graphics Computer Systems, Inc.
281debfc3dSmrg *
291debfc3dSmrg * Permission to use, copy, modify, distribute and sell this software
301debfc3dSmrg * and its documentation for any purpose is hereby granted without fee,
311debfc3dSmrg * provided that the above copyright notice appear in all copies and
321debfc3dSmrg * that both that copyright notice and this permission notice appear
331debfc3dSmrg * in supporting documentation. Silicon Graphics makes no
341debfc3dSmrg * representations about the suitability of this software for any
351debfc3dSmrg * purpose. It is provided "as is" without express or implied warranty.
361debfc3dSmrg */
371debfc3dSmrg
381debfc3dSmrg /** @file bits/allocator.h
391debfc3dSmrg * This is an internal header file, included by other library headers.
401debfc3dSmrg * Do not attempt to use it directly. @headername{memory}
411debfc3dSmrg */
421debfc3dSmrg
431debfc3dSmrg #ifndef _ALLOCATOR_H
441debfc3dSmrg #define _ALLOCATOR_H 1
451debfc3dSmrg
461debfc3dSmrg #include <bits/c++allocator.h> // Define the base class to std::allocator.
471debfc3dSmrg #include <bits/memoryfwd.h>
481debfc3dSmrg #if __cplusplus >= 201103L
491debfc3dSmrg #include <type_traits>
501debfc3dSmrg #endif
511debfc3dSmrg
521debfc3dSmrg #define __cpp_lib_incomplete_container_elements 201505
531debfc3dSmrg
_GLIBCXX_VISIBILITY(default)541debfc3dSmrg namespace std _GLIBCXX_VISIBILITY(default)
551debfc3dSmrg {
561debfc3dSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
571debfc3dSmrg
581debfc3dSmrg /**
591debfc3dSmrg * @addtogroup allocators
601debfc3dSmrg * @{
611debfc3dSmrg */
621debfc3dSmrg
63*8feb0f0bSmrg // Since C++20 the primary template should be used for allocator<void>,
64*8feb0f0bSmrg // but then it would have a non-trivial default ctor and dtor for C++20,
65*8feb0f0bSmrg // but trivial for C++98-17, which would be an ABI incompatibiliy between
66*8feb0f0bSmrg // different standard dialects. So C++20 still uses the allocator<void>
67*8feb0f0bSmrg // explicit specialization, with the historical ABI properties, but with
68*8feb0f0bSmrg // the same members that are present in the primary template.
69*8feb0f0bSmrg
701debfc3dSmrg /// allocator<void> specialization.
711debfc3dSmrg template<>
721debfc3dSmrg class allocator<void>
731debfc3dSmrg {
741debfc3dSmrg public:
75*8feb0f0bSmrg typedef void value_type;
761debfc3dSmrg typedef size_t size_type;
771debfc3dSmrg typedef ptrdiff_t difference_type;
78*8feb0f0bSmrg
79*8feb0f0bSmrg #if __cplusplus <= 201703L
80*8feb0f0bSmrg // These were removed for C++20, allocator_traits does the right thing.
811debfc3dSmrg typedef void* pointer;
821debfc3dSmrg typedef const void* const_pointer;
831debfc3dSmrg
841debfc3dSmrg template<typename _Tp1>
851debfc3dSmrg struct rebind
861debfc3dSmrg { typedef allocator<_Tp1> other; };
87*8feb0f0bSmrg #endif
881debfc3dSmrg
891debfc3dSmrg #if __cplusplus >= 201103L
901debfc3dSmrg // _GLIBCXX_RESOLVE_LIB_DEFECTS
911debfc3dSmrg // 2103. std::allocator propagate_on_container_move_assignment
921debfc3dSmrg typedef true_type propagate_on_container_move_assignment;
931debfc3dSmrg
941debfc3dSmrg typedef true_type is_always_equal;
951debfc3dSmrg
96*8feb0f0bSmrg #if __cplusplus > 201703L
97*8feb0f0bSmrg // As noted above, these members are present for C++20 to provide the
98*8feb0f0bSmrg // same API as the primary template, but still trivial as in pre-C++20.
99*8feb0f0bSmrg allocator() = default;
100*8feb0f0bSmrg ~allocator() = default;
1011debfc3dSmrg
1021debfc3dSmrg template<typename _Up>
103*8feb0f0bSmrg constexpr
104*8feb0f0bSmrg allocator(const allocator<_Up>&) noexcept { }
105*8feb0f0bSmrg
106*8feb0f0bSmrg // No allocate member because it's ill-formed by LWG 3307.
107*8feb0f0bSmrg // No deallocate member because it would be undefined to call it
108*8feb0f0bSmrg // with any pointer which wasn't obtained from allocate.
109*8feb0f0bSmrg #endif // C++20
110*8feb0f0bSmrg #endif // C++11
1111debfc3dSmrg };
1121debfc3dSmrg
1131debfc3dSmrg /**
114*8feb0f0bSmrg * @brief The @a standard allocator, as per C++03 [20.4.1].
1151debfc3dSmrg *
1161debfc3dSmrg * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.allocator
1171debfc3dSmrg * for further details.
1181debfc3dSmrg *
1191debfc3dSmrg * @tparam _Tp Type of allocated object.
1201debfc3dSmrg */
1211debfc3dSmrg template<typename _Tp>
1221debfc3dSmrg class allocator : public __allocator_base<_Tp>
1231debfc3dSmrg {
1241debfc3dSmrg public:
125*8feb0f0bSmrg typedef _Tp value_type;
1261debfc3dSmrg typedef size_t size_type;
1271debfc3dSmrg typedef ptrdiff_t difference_type;
128*8feb0f0bSmrg
129*8feb0f0bSmrg #if __cplusplus <= 201703L
130*8feb0f0bSmrg // These were removed for C++20.
1311debfc3dSmrg typedef _Tp* pointer;
1321debfc3dSmrg typedef const _Tp* const_pointer;
1331debfc3dSmrg typedef _Tp& reference;
1341debfc3dSmrg typedef const _Tp& const_reference;
1351debfc3dSmrg
1361debfc3dSmrg template<typename _Tp1>
1371debfc3dSmrg struct rebind
1381debfc3dSmrg { typedef allocator<_Tp1> other; };
139*8feb0f0bSmrg #endif
1401debfc3dSmrg
1411debfc3dSmrg #if __cplusplus >= 201103L
1421debfc3dSmrg // _GLIBCXX_RESOLVE_LIB_DEFECTS
1431debfc3dSmrg // 2103. std::allocator propagate_on_container_move_assignment
1441debfc3dSmrg typedef true_type propagate_on_container_move_assignment;
1451debfc3dSmrg
1461debfc3dSmrg typedef true_type is_always_equal;
1471debfc3dSmrg #endif
1481debfc3dSmrg
149c0a68be4Smrg // _GLIBCXX_RESOLVE_LIB_DEFECTS
150c0a68be4Smrg // 3035. std::allocator's constructors should be constexpr
151c0a68be4Smrg _GLIBCXX20_CONSTEXPR
152c0a68be4Smrg allocator() _GLIBCXX_NOTHROW { }
1531debfc3dSmrg
154c0a68be4Smrg _GLIBCXX20_CONSTEXPR
155c0a68be4Smrg allocator(const allocator& __a) _GLIBCXX_NOTHROW
1561debfc3dSmrg : __allocator_base<_Tp>(__a) { }
1571debfc3dSmrg
158c0a68be4Smrg #if __cplusplus >= 201103L
159c0a68be4Smrg // Avoid implicit deprecation.
160c0a68be4Smrg allocator& operator=(const allocator&) = default;
161c0a68be4Smrg #endif
1621debfc3dSmrg
163c0a68be4Smrg template<typename _Tp1>
164c0a68be4Smrg _GLIBCXX20_CONSTEXPR
165c0a68be4Smrg allocator(const allocator<_Tp1>&) _GLIBCXX_NOTHROW { }
166c0a68be4Smrg
167*8feb0f0bSmrg #if __cpp_constexpr_dynamic_alloc
168*8feb0f0bSmrg constexpr
169*8feb0f0bSmrg #endif
170c0a68be4Smrg ~allocator() _GLIBCXX_NOTHROW { }
171c0a68be4Smrg
172*8feb0f0bSmrg #if __cplusplus > 201703L
173*8feb0f0bSmrg [[nodiscard,__gnu__::__always_inline__]]
174*8feb0f0bSmrg constexpr _Tp*
175*8feb0f0bSmrg allocate(size_t __n)
176*8feb0f0bSmrg {
177*8feb0f0bSmrg #ifdef __cpp_lib_is_constant_evaluated
178*8feb0f0bSmrg if (std::is_constant_evaluated())
179*8feb0f0bSmrg return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
180*8feb0f0bSmrg #endif
181*8feb0f0bSmrg return __allocator_base<_Tp>::allocate(__n, 0);
182*8feb0f0bSmrg }
183*8feb0f0bSmrg
184*8feb0f0bSmrg [[__gnu__::__always_inline__]]
185*8feb0f0bSmrg constexpr void
186*8feb0f0bSmrg deallocate(_Tp* __p, size_t __n)
187*8feb0f0bSmrg {
188*8feb0f0bSmrg #ifdef __cpp_lib_is_constant_evaluated
189*8feb0f0bSmrg if (std::is_constant_evaluated())
190*8feb0f0bSmrg {
191*8feb0f0bSmrg ::operator delete(__p);
192*8feb0f0bSmrg return;
193*8feb0f0bSmrg }
194*8feb0f0bSmrg #endif
195*8feb0f0bSmrg __allocator_base<_Tp>::deallocate(__p, __n);
196*8feb0f0bSmrg }
197*8feb0f0bSmrg #endif // C++20
198*8feb0f0bSmrg
199*8feb0f0bSmrg friend _GLIBCXX20_CONSTEXPR bool
200c0a68be4Smrg operator==(const allocator&, const allocator&) _GLIBCXX_NOTHROW
201c0a68be4Smrg { return true; }
202c0a68be4Smrg
203*8feb0f0bSmrg #if __cpp_impl_three_way_comparison < 201907L
204*8feb0f0bSmrg friend _GLIBCXX20_CONSTEXPR bool
205c0a68be4Smrg operator!=(const allocator&, const allocator&) _GLIBCXX_NOTHROW
206c0a68be4Smrg { return false; }
207*8feb0f0bSmrg #endif
2081debfc3dSmrg
2091debfc3dSmrg // Inherit everything else.
2101debfc3dSmrg };
2111debfc3dSmrg
2121debfc3dSmrg template<typename _T1, typename _T2>
213*8feb0f0bSmrg inline _GLIBCXX20_CONSTEXPR bool
2141debfc3dSmrg operator==(const allocator<_T1>&, const allocator<_T2>&)
215c0a68be4Smrg _GLIBCXX_NOTHROW
2161debfc3dSmrg { return true; }
2171debfc3dSmrg
218*8feb0f0bSmrg #if __cpp_impl_three_way_comparison < 201907L
2191debfc3dSmrg template<typename _T1, typename _T2>
220*8feb0f0bSmrg inline _GLIBCXX20_CONSTEXPR bool
2211debfc3dSmrg operator!=(const allocator<_T1>&, const allocator<_T2>&)
222c0a68be4Smrg _GLIBCXX_NOTHROW
2231debfc3dSmrg { return false; }
224*8feb0f0bSmrg #endif
2251debfc3dSmrg
226a2dc1f3fSmrg // Invalid allocator<cv T> partial specializations.
227a2dc1f3fSmrg // allocator_traits::rebind_alloc can be used to form a valid allocator type.
228a2dc1f3fSmrg template<typename _Tp>
229a2dc1f3fSmrg class allocator<const _Tp>
230a2dc1f3fSmrg {
231a2dc1f3fSmrg public:
232a2dc1f3fSmrg typedef _Tp value_type;
233a2dc1f3fSmrg template<typename _Up> allocator(const allocator<_Up>&) { }
234a2dc1f3fSmrg };
235a2dc1f3fSmrg
236a2dc1f3fSmrg template<typename _Tp>
237a2dc1f3fSmrg class allocator<volatile _Tp>
238a2dc1f3fSmrg {
239a2dc1f3fSmrg public:
240a2dc1f3fSmrg typedef _Tp value_type;
241a2dc1f3fSmrg template<typename _Up> allocator(const allocator<_Up>&) { }
242a2dc1f3fSmrg };
243a2dc1f3fSmrg
244a2dc1f3fSmrg template<typename _Tp>
245a2dc1f3fSmrg class allocator<const volatile _Tp>
246a2dc1f3fSmrg {
247a2dc1f3fSmrg public:
248a2dc1f3fSmrg typedef _Tp value_type;
249a2dc1f3fSmrg template<typename _Up> allocator(const allocator<_Up>&) { }
250a2dc1f3fSmrg };
251a2dc1f3fSmrg
2521debfc3dSmrg /// @} group allocator
2531debfc3dSmrg
2541debfc3dSmrg // Inhibit implicit instantiations for required instantiations,
2551debfc3dSmrg // which are defined via explicit instantiations elsewhere.
2561debfc3dSmrg #if _GLIBCXX_EXTERN_TEMPLATE
2571debfc3dSmrg extern template class allocator<char>;
2581debfc3dSmrg extern template class allocator<wchar_t>;
2591debfc3dSmrg #endif
2601debfc3dSmrg
2611debfc3dSmrg // Undefine.
2621debfc3dSmrg #undef __allocator_base
2631debfc3dSmrg
2641debfc3dSmrg // To implement Option 3 of DR 431.
2651debfc3dSmrg template<typename _Alloc, bool = __is_empty(_Alloc)>
2661debfc3dSmrg struct __alloc_swap
2671debfc3dSmrg { static void _S_do_it(_Alloc&, _Alloc&) _GLIBCXX_NOEXCEPT { } };
2681debfc3dSmrg
2691debfc3dSmrg template<typename _Alloc>
2701debfc3dSmrg struct __alloc_swap<_Alloc, false>
2711debfc3dSmrg {
2721debfc3dSmrg static void
2731debfc3dSmrg _S_do_it(_Alloc& __one, _Alloc& __two) _GLIBCXX_NOEXCEPT
2741debfc3dSmrg {
2751debfc3dSmrg // Precondition: swappable allocators.
2761debfc3dSmrg if (__one != __two)
2771debfc3dSmrg swap(__one, __two);
2781debfc3dSmrg }
2791debfc3dSmrg };
2801debfc3dSmrg
2811debfc3dSmrg // Optimize for stateless allocators.
2821debfc3dSmrg template<typename _Alloc, bool = __is_empty(_Alloc)>
2831debfc3dSmrg struct __alloc_neq
2841debfc3dSmrg {
2851debfc3dSmrg static bool
2861debfc3dSmrg _S_do_it(const _Alloc&, const _Alloc&)
2871debfc3dSmrg { return false; }
2881debfc3dSmrg };
2891debfc3dSmrg
2901debfc3dSmrg template<typename _Alloc>
2911debfc3dSmrg struct __alloc_neq<_Alloc, false>
2921debfc3dSmrg {
2931debfc3dSmrg static bool
2941debfc3dSmrg _S_do_it(const _Alloc& __one, const _Alloc& __two)
2951debfc3dSmrg { return __one != __two; }
2961debfc3dSmrg };
2971debfc3dSmrg
2981debfc3dSmrg #if __cplusplus >= 201103L
2991debfc3dSmrg template<typename _Tp, bool
3001debfc3dSmrg = __or_<is_copy_constructible<typename _Tp::value_type>,
3011debfc3dSmrg is_nothrow_move_constructible<typename _Tp::value_type>>::value>
3021debfc3dSmrg struct __shrink_to_fit_aux
3031debfc3dSmrg { static bool _S_do_it(_Tp&) noexcept { return false; } };
3041debfc3dSmrg
3051debfc3dSmrg template<typename _Tp>
3061debfc3dSmrg struct __shrink_to_fit_aux<_Tp, true>
3071debfc3dSmrg {
3081debfc3dSmrg static bool
3091debfc3dSmrg _S_do_it(_Tp& __c) noexcept
3101debfc3dSmrg {
3111debfc3dSmrg #if __cpp_exceptions
3121debfc3dSmrg try
3131debfc3dSmrg {
3141debfc3dSmrg _Tp(__make_move_if_noexcept_iterator(__c.begin()),
3151debfc3dSmrg __make_move_if_noexcept_iterator(__c.end()),
3161debfc3dSmrg __c.get_allocator()).swap(__c);
3171debfc3dSmrg return true;
3181debfc3dSmrg }
3191debfc3dSmrg catch(...)
3201debfc3dSmrg { return false; }
3211debfc3dSmrg #else
3221debfc3dSmrg return false;
3231debfc3dSmrg #endif
3241debfc3dSmrg }
3251debfc3dSmrg };
3261debfc3dSmrg #endif
3271debfc3dSmrg
3281debfc3dSmrg _GLIBCXX_END_NAMESPACE_VERSION
3291debfc3dSmrg } // namespace std
3301debfc3dSmrg
3311debfc3dSmrg #endif
332