]>
Commit | Line | Data |
---|---|---|
e8eb60bd JW |
1 | // Allocator traits -*- C++ -*- |
2 | ||
a5544970 | 3 | // Copyright (C) 2011-2019 Free Software Foundation, Inc. |
e8eb60bd JW |
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 | ||
93c66bc6 BK |
25 | /** @file bits/alloc_traits.h |
26 | * This is an internal header file, included by other library headers. | |
a5db4ced | 27 | * Do not attempt to use it directly. @headername{memory} |
93c66bc6 BK |
28 | */ |
29 | ||
e8eb60bd JW |
30 | #ifndef _ALLOC_TRAITS_H |
31 | #define _ALLOC_TRAITS_H 1 | |
32 | ||
734f5023 | 33 | #if __cplusplus >= 201103L |
e8eb60bd | 34 | |
cd1e6665 | 35 | #include <bits/memoryfwd.h> |
e8eb60bd JW |
36 | #include <bits/ptr_traits.h> |
37 | #include <ext/numeric_traits.h> | |
38 | ||
db23e4c4 JW |
39 | #define __cpp_lib_allocator_traits_is_always_equal 201411 |
40 | ||
e8eb60bd JW |
41 | namespace std _GLIBCXX_VISIBILITY(default) |
42 | { | |
43 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
44 | ||
79466838 JW |
45 | struct __allocator_traits_base |
46 | { | |
a3a1620b JW |
47 | template<typename _Tp, typename _Up, typename = void> |
48 | struct __rebind : __replace_first_arg<_Tp, _Up> { }; | |
49 | ||
50 | template<typename _Tp, typename _Up> | |
51 | struct __rebind<_Tp, _Up, | |
52 | __void_t<typename _Tp::template rebind<_Up>::other>> | |
53 | { using type = typename _Tp::template rebind<_Up>::other; }; | |
79466838 JW |
54 | |
55 | protected: | |
56 | template<typename _Tp> | |
57 | using __pointer = typename _Tp::pointer; | |
58 | template<typename _Tp> | |
59 | using __c_pointer = typename _Tp::const_pointer; | |
60 | template<typename _Tp> | |
61 | using __v_pointer = typename _Tp::void_pointer; | |
62 | template<typename _Tp> | |
63 | using __cv_pointer = typename _Tp::const_void_pointer; | |
79466838 JW |
64 | template<typename _Tp> |
65 | using __pocca = typename _Tp::propagate_on_container_copy_assignment; | |
66 | template<typename _Tp> | |
67 | using __pocma = typename _Tp::propagate_on_container_move_assignment; | |
68 | template<typename _Tp> | |
69 | using __pocs = typename _Tp::propagate_on_container_swap; | |
70 | template<typename _Tp> | |
71 | using __equal = typename _Tp::is_always_equal; | |
72 | }; | |
73 | ||
74 | template<typename _Alloc, typename _Up> | |
a3a1620b JW |
75 | using __alloc_rebind |
76 | = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type; | |
484dc599 | 77 | |
e8eb60bd JW |
78 | /** |
79 | * @brief Uniform interface to all allocator types. | |
80 | * @ingroup allocators | |
81 | */ | |
82 | template<typename _Alloc> | |
79466838 | 83 | struct allocator_traits : __allocator_traits_base |
e8eb60bd JW |
84 | { |
85 | /// The allocator type | |
86 | typedef _Alloc allocator_type; | |
87 | /// The allocated type | |
88 | typedef typename _Alloc::value_type value_type; | |
89 | ||
e8eb60bd JW |
90 | /** |
91 | * @brief The allocator's pointer type. | |
92 | * | |
93 | * @c Alloc::pointer if that type exists, otherwise @c value_type* | |
94 | */ | |
79466838 | 95 | using pointer = __detected_or_t<value_type*, __pointer, _Alloc>; |
e8eb60bd | 96 | |
4dfdda10 JW |
97 | private: |
98 | // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp> | |
99 | template<template<typename> class _Func, typename _Tp, typename = void> | |
100 | struct _Ptr | |
101 | { | |
102 | using type = typename pointer_traits<pointer>::template rebind<_Tp>; | |
103 | }; | |
104 | ||
105 | template<template<typename> class _Func, typename _Tp> | |
106 | struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>> | |
107 | { | |
108 | using type = _Func<_Alloc>; | |
109 | }; | |
110 | ||
111 | // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type | |
112 | template<typename _A2, typename _PtrT, typename = void> | |
113 | struct _Diff | |
114 | { using type = typename pointer_traits<_PtrT>::difference_type; }; | |
115 | ||
116 | template<typename _A2, typename _PtrT> | |
117 | struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>> | |
118 | { using type = typename _A2::difference_type; }; | |
119 | ||
120 | // Select _A2::size_type or make_unsigned<_DiffT>::type | |
121 | template<typename _A2, typename _DiffT, typename = void> | |
122 | struct _Size : make_unsigned<_DiffT> { }; | |
123 | ||
124 | template<typename _A2, typename _DiffT> | |
125 | struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>> | |
126 | { using type = typename _A2::size_type; }; | |
127 | ||
128 | public: | |
e8eb60bd JW |
129 | /** |
130 | * @brief The allocator's const pointer type. | |
131 | * | |
132 | * @c Alloc::const_pointer if that type exists, otherwise | |
133 | * <tt> pointer_traits<pointer>::rebind<const value_type> </tt> | |
134 | */ | |
4dfdda10 | 135 | using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; |
e8eb60bd JW |
136 | |
137 | /** | |
138 | * @brief The allocator's void pointer type. | |
139 | * | |
140 | * @c Alloc::void_pointer if that type exists, otherwise | |
141 | * <tt> pointer_traits<pointer>::rebind<void> </tt> | |
142 | */ | |
4dfdda10 | 143 | using void_pointer = typename _Ptr<__v_pointer, void>::type; |
e8eb60bd JW |
144 | |
145 | /** | |
146 | * @brief The allocator's const void pointer type. | |
147 | * | |
148 | * @c Alloc::const_void_pointer if that type exists, otherwise | |
149 | * <tt> pointer_traits<pointer>::rebind<const void> </tt> | |
150 | */ | |
4dfdda10 | 151 | using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type; |
e8eb60bd JW |
152 | |
153 | /** | |
154 | * @brief The allocator's difference type | |
155 | * | |
156 | * @c Alloc::difference_type if that type exists, otherwise | |
157 | * <tt> pointer_traits<pointer>::difference_type </tt> | |
158 | */ | |
4dfdda10 | 159 | using difference_type = typename _Diff<_Alloc, pointer>::type; |
e8eb60bd JW |
160 | |
161 | /** | |
162 | * @brief The allocator's size type | |
163 | * | |
164 | * @c Alloc::size_type if that type exists, otherwise | |
165 | * <tt> make_unsigned<difference_type>::type </tt> | |
166 | */ | |
4dfdda10 | 167 | using size_type = typename _Size<_Alloc, difference_type>::type; |
e8eb60bd JW |
168 | |
169 | /** | |
170 | * @brief How the allocator is propagated on copy assignment | |
171 | * | |
172 | * @c Alloc::propagate_on_container_copy_assignment if that type exists, | |
173 | * otherwise @c false_type | |
174 | */ | |
79466838 JW |
175 | using propagate_on_container_copy_assignment |
176 | = __detected_or_t<false_type, __pocca, _Alloc>; | |
e8eb60bd JW |
177 | |
178 | /** | |
179 | * @brief How the allocator is propagated on move assignment | |
180 | * | |
181 | * @c Alloc::propagate_on_container_move_assignment if that type exists, | |
182 | * otherwise @c false_type | |
183 | */ | |
79466838 JW |
184 | using propagate_on_container_move_assignment |
185 | = __detected_or_t<false_type, __pocma, _Alloc>; | |
e8eb60bd JW |
186 | |
187 | /** | |
188 | * @brief How the allocator is propagated on swap | |
189 | * | |
190 | * @c Alloc::propagate_on_container_swap if that type exists, | |
191 | * otherwise @c false_type | |
192 | */ | |
79466838 JW |
193 | using propagate_on_container_swap |
194 | = __detected_or_t<false_type, __pocs, _Alloc>; | |
a2b5fdcb JW |
195 | |
196 | /** | |
197 | * @brief Whether all instances of the allocator type compare equal. | |
198 | * | |
199 | * @c Alloc::is_always_equal if that type exists, | |
200 | * otherwise @c is_empty<Alloc>::type | |
201 | */ | |
79466838 JW |
202 | using is_always_equal |
203 | = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>; | |
e8eb60bd | 204 | |
e8eb60bd | 205 | template<typename _Tp> |
79466838 | 206 | using rebind_alloc = __alloc_rebind<_Alloc, _Tp>; |
e8eb60bd | 207 | template<typename _Tp> |
20067423 | 208 | using rebind_traits = allocator_traits<rebind_alloc<_Tp>>; |
e8eb60bd | 209 | |
79466838 | 210 | private: |
e8eb60bd | 211 | template<typename _Alloc2> |
79466838 JW |
212 | static auto |
213 | _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int) | |
214 | -> decltype(__a.allocate(__n, __hint)) | |
e8eb60bd JW |
215 | { return __a.allocate(__n, __hint); } |
216 | ||
79466838 | 217 | template<typename _Alloc2> |
20067423 | 218 | static pointer |
79466838 | 219 | _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...) |
e8eb60bd JW |
220 | { return __a.allocate(__n); } |
221 | ||
222 | template<typename _Tp, typename... _Args> | |
223 | struct __construct_helper | |
224 | { | |
225 | template<typename _Alloc2, | |
226 | typename = decltype(std::declval<_Alloc2*>()->construct( | |
227 | std::declval<_Tp*>(), std::declval<_Args>()...))> | |
228 | static true_type __test(int); | |
229 | ||
230 | template<typename> | |
231 | static false_type __test(...); | |
232 | ||
20067423 | 233 | using type = decltype(__test<_Alloc>(0)); |
e8eb60bd JW |
234 | }; |
235 | ||
236 | template<typename _Tp, typename... _Args> | |
20067423 JW |
237 | using __has_construct |
238 | = typename __construct_helper<_Tp, _Args...>::type; | |
239 | ||
240 | template<typename _Tp, typename... _Args> | |
241 | static _Require<__has_construct<_Tp, _Args...>> | |
242 | _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args) | |
0f317ef7 | 243 | noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...))) |
e8eb60bd JW |
244 | { __a.construct(__p, std::forward<_Args>(__args)...); } |
245 | ||
246 | template<typename _Tp, typename... _Args> | |
20067423 JW |
247 | static |
248 | _Require<__and_<__not_<__has_construct<_Tp, _Args...>>, | |
249 | is_constructible<_Tp, _Args...>>> | |
250 | _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) | |
0f317ef7 MG |
251 | noexcept(noexcept(::new((void*)__p) |
252 | _Tp(std::forward<_Args>(__args)...))) | |
e8eb60bd JW |
253 | { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); } |
254 | ||
79466838 JW |
255 | template<typename _Alloc2, typename _Tp> |
256 | static auto | |
257 | _S_destroy(_Alloc2& __a, _Tp* __p, int) | |
0f317ef7 | 258 | noexcept(noexcept(__a.destroy(__p))) |
79466838 | 259 | -> decltype(__a.destroy(__p)) |
e8eb60bd JW |
260 | { __a.destroy(__p); } |
261 | ||
79466838 JW |
262 | template<typename _Alloc2, typename _Tp> |
263 | static void | |
264 | _S_destroy(_Alloc2&, _Tp* __p, ...) | |
0f317ef7 | 265 | noexcept(noexcept(__p->~_Tp())) |
e8eb60bd JW |
266 | { __p->~_Tp(); } |
267 | ||
268 | template<typename _Alloc2> | |
79466838 | 269 | static auto |
20067423 | 270 | _S_max_size(_Alloc2& __a, int) |
79466838 | 271 | -> decltype(__a.max_size()) |
e8eb60bd JW |
272 | { return __a.max_size(); } |
273 | ||
79466838 | 274 | template<typename _Alloc2> |
20067423 JW |
275 | static size_type |
276 | _S_max_size(_Alloc2&, ...) | |
32e6a60e JW |
277 | { |
278 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
279 | // 2466. allocator_traits::max_size() default behavior is incorrect | |
280 | return __gnu_cxx::__numeric_traits<size_type>::__max | |
281 | / sizeof(value_type); | |
282 | } | |
e8eb60bd JW |
283 | |
284 | template<typename _Alloc2> | |
79466838 | 285 | static auto |
20067423 | 286 | _S_select(_Alloc2& __a, int) |
79466838 | 287 | -> decltype(__a.select_on_container_copy_construction()) |
e8eb60bd JW |
288 | { return __a.select_on_container_copy_construction(); } |
289 | ||
79466838 | 290 | template<typename _Alloc2> |
20067423 JW |
291 | static _Alloc2 |
292 | _S_select(_Alloc2& __a, ...) | |
e8eb60bd JW |
293 | { return __a; } |
294 | ||
295 | public: | |
296 | ||
297 | /** | |
298 | * @brief Allocate memory. | |
93c66bc6 BK |
299 | * @param __a An allocator. |
300 | * @param __n The number of objects to allocate space for. | |
e8eb60bd JW |
301 | * |
302 | * Calls @c a.allocate(n) | |
303 | */ | |
304 | static pointer | |
305 | allocate(_Alloc& __a, size_type __n) | |
306 | { return __a.allocate(__n); } | |
307 | ||
308 | /** | |
309 | * @brief Allocate memory. | |
93c66bc6 BK |
310 | * @param __a An allocator. |
311 | * @param __n The number of objects to allocate space for. | |
312 | * @param __hint Aid to locality. | |
e8eb60bd JW |
313 | * @return Memory of suitable size and alignment for @a n objects |
314 | * of type @c value_type | |
315 | * | |
316 | * Returns <tt> a.allocate(n, hint) </tt> if that expression is | |
317 | * well-formed, otherwise returns @c a.allocate(n) | |
318 | */ | |
319 | static pointer | |
320 | allocate(_Alloc& __a, size_type __n, const_void_pointer __hint) | |
79466838 | 321 | { return _S_allocate(__a, __n, __hint, 0); } |
e8eb60bd JW |
322 | |
323 | /** | |
324 | * @brief Deallocate memory. | |
93c66bc6 BK |
325 | * @param __a An allocator. |
326 | * @param __p Pointer to the memory to deallocate. | |
327 | * @param __n The number of objects space was allocated for. | |
e8eb60bd JW |
328 | * |
329 | * Calls <tt> a.deallocate(p, n) </tt> | |
330 | */ | |
79466838 JW |
331 | static void |
332 | deallocate(_Alloc& __a, pointer __p, size_type __n) | |
e8eb60bd JW |
333 | { __a.deallocate(__p, __n); } |
334 | ||
335 | /** | |
93c66bc6 BK |
336 | * @brief Construct an object of type @a _Tp |
337 | * @param __a An allocator. | |
338 | * @param __p Pointer to memory of suitable size and alignment for Tp | |
339 | * @param __args Constructor arguments. | |
e8eb60bd | 340 | * |
93c66bc6 | 341 | * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt> |
e8eb60bd | 342 | * if that expression is well-formed, otherwise uses placement-new |
93c66bc6 BK |
343 | * to construct an object of type @a _Tp at location @a __p from the |
344 | * arguments @a __args... | |
e8eb60bd JW |
345 | */ |
346 | template<typename _Tp, typename... _Args> | |
b7202baf | 347 | static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args) |
0f317ef7 MG |
348 | noexcept(noexcept(_S_construct(__a, __p, |
349 | std::forward<_Args>(__args)...))) | |
b7202baf | 350 | -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...)) |
e8eb60bd JW |
351 | { _S_construct(__a, __p, std::forward<_Args>(__args)...); } |
352 | ||
353 | /** | |
93c66bc6 BK |
354 | * @brief Destroy an object of type @a _Tp |
355 | * @param __a An allocator. | |
356 | * @param __p Pointer to the object to destroy | |
e8eb60bd | 357 | * |
93c66bc6 BK |
358 | * Calls @c __a.destroy(__p) if that expression is well-formed, |
359 | * otherwise calls @c __p->~_Tp() | |
e8eb60bd | 360 | */ |
1517bc30 | 361 | template<typename _Tp> |
e8eb60bd | 362 | static void destroy(_Alloc& __a, _Tp* __p) |
0f317ef7 | 363 | noexcept(noexcept(_S_destroy(__a, __p, 0))) |
79466838 | 364 | { _S_destroy(__a, __p, 0); } |
e8eb60bd JW |
365 | |
366 | /** | |
367 | * @brief The maximum supported allocation size | |
93c66bc6 BK |
368 | * @param __a An allocator. |
369 | * @return @c __a.max_size() or @c numeric_limits<size_type>::max() | |
e8eb60bd | 370 | * |
93c66bc6 | 371 | * Returns @c __a.max_size() if that expression is well-formed, |
e8eb60bd JW |
372 | * otherwise returns @c numeric_limits<size_type>::max() |
373 | */ | |
7b916902 | 374 | static size_type max_size(const _Alloc& __a) noexcept |
20067423 | 375 | { return _S_max_size(__a, 0); } |
e8eb60bd JW |
376 | |
377 | /** | |
378 | * @brief Obtain an allocator to use when copying a container. | |
93c66bc6 BK |
379 | * @param __rhs An allocator. |
380 | * @return @c __rhs.select_on_container_copy_construction() or @a __rhs | |
e8eb60bd | 381 | * |
93c66bc6 BK |
382 | * Returns @c __rhs.select_on_container_copy_construction() if that |
383 | * expression is well-formed, otherwise returns @a __rhs | |
e8eb60bd JW |
384 | */ |
385 | static _Alloc | |
386 | select_on_container_copy_construction(const _Alloc& __rhs) | |
20067423 | 387 | { return _S_select(__rhs, 0); } |
e8eb60bd JW |
388 | }; |
389 | ||
1517bc30 JW |
390 | /// Partial specialization for std::allocator. |
391 | template<typename _Tp> | |
392 | struct allocator_traits<allocator<_Tp>> | |
393 | { | |
394 | /// The allocator type | |
395 | using allocator_type = allocator<_Tp>; | |
396 | /// The allocated type | |
397 | using value_type = _Tp; | |
398 | ||
399 | /// The allocator's pointer type. | |
400 | using pointer = _Tp*; | |
401 | ||
402 | /// The allocator's const pointer type. | |
403 | using const_pointer = const _Tp*; | |
404 | ||
405 | /// The allocator's void pointer type. | |
406 | using void_pointer = void*; | |
407 | ||
408 | /// The allocator's const void pointer type. | |
409 | using const_void_pointer = const void*; | |
410 | ||
411 | /// The allocator's difference type | |
412 | using difference_type = std::ptrdiff_t; | |
413 | ||
414 | /// The allocator's size type | |
415 | using size_type = std::size_t; | |
416 | ||
417 | /// How the allocator is propagated on copy assignment | |
418 | using propagate_on_container_copy_assignment = false_type; | |
419 | ||
420 | /// How the allocator is propagated on move assignment | |
421 | using propagate_on_container_move_assignment = true_type; | |
422 | ||
423 | /// How the allocator is propagated on swap | |
424 | using propagate_on_container_swap = false_type; | |
425 | ||
426 | /// Whether all instances of the allocator type compare equal. | |
427 | using is_always_equal = true_type; | |
428 | ||
429 | template<typename _Up> | |
430 | using rebind_alloc = allocator<_Up>; | |
431 | ||
432 | template<typename _Up> | |
433 | using rebind_traits = allocator_traits<allocator<_Up>>; | |
434 | ||
435 | /** | |
436 | * @brief Allocate memory. | |
437 | * @param __a An allocator. | |
438 | * @param __n The number of objects to allocate space for. | |
439 | * | |
440 | * Calls @c a.allocate(n) | |
441 | */ | |
442 | static pointer | |
443 | allocate(allocator_type& __a, size_type __n) | |
444 | { return __a.allocate(__n); } | |
445 | ||
446 | /** | |
447 | * @brief Allocate memory. | |
448 | * @param __a An allocator. | |
449 | * @param __n The number of objects to allocate space for. | |
450 | * @param __hint Aid to locality. | |
451 | * @return Memory of suitable size and alignment for @a n objects | |
452 | * of type @c value_type | |
453 | * | |
454 | * Returns <tt> a.allocate(n, hint) </tt> | |
455 | */ | |
456 | static pointer | |
457 | allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) | |
458 | { return __a.allocate(__n, __hint); } | |
459 | ||
460 | /** | |
461 | * @brief Deallocate memory. | |
462 | * @param __a An allocator. | |
463 | * @param __p Pointer to the memory to deallocate. | |
464 | * @param __n The number of objects space was allocated for. | |
465 | * | |
466 | * Calls <tt> a.deallocate(p, n) </tt> | |
467 | */ | |
468 | static void | |
469 | deallocate(allocator_type& __a, pointer __p, size_type __n) | |
470 | { __a.deallocate(__p, __n); } | |
471 | ||
472 | /** | |
473 | * @brief Construct an object of type @a _Up | |
474 | * @param __a An allocator. | |
475 | * @param __p Pointer to memory of suitable size and alignment for Tp | |
476 | * @param __args Constructor arguments. | |
477 | * | |
478 | * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt> | |
479 | */ | |
480 | template<typename _Up, typename... _Args> | |
481 | static void | |
482 | construct(allocator_type& __a, _Up* __p, _Args&&... __args) | |
0f317ef7 | 483 | noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...))) |
1517bc30 JW |
484 | { __a.construct(__p, std::forward<_Args>(__args)...); } |
485 | ||
486 | /** | |
487 | * @brief Destroy an object of type @a _Up | |
488 | * @param __a An allocator. | |
489 | * @param __p Pointer to the object to destroy | |
490 | * | |
491 | * Calls @c __a.destroy(__p). | |
492 | */ | |
493 | template<typename _Up> | |
494 | static void | |
495 | destroy(allocator_type& __a, _Up* __p) | |
0f317ef7 | 496 | noexcept(noexcept(__a.destroy(__p))) |
1517bc30 JW |
497 | { __a.destroy(__p); } |
498 | ||
499 | /** | |
500 | * @brief The maximum supported allocation size | |
501 | * @param __a An allocator. | |
502 | * @return @c __a.max_size() | |
503 | */ | |
504 | static size_type | |
505 | max_size(const allocator_type& __a) noexcept | |
506 | { return __a.max_size(); } | |
507 | ||
508 | /** | |
509 | * @brief Obtain an allocator to use when copying a container. | |
510 | * @param __rhs An allocator. | |
511 | * @return @c __rhs | |
512 | */ | |
513 | static allocator_type | |
514 | select_on_container_copy_construction(const allocator_type& __rhs) | |
515 | { return __rhs; } | |
516 | }; | |
517 | ||
518 | ||
e8eb60bd JW |
519 | template<typename _Alloc> |
520 | inline void | |
521 | __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) | |
522 | { __one = __two; } | |
523 | ||
524 | template<typename _Alloc> | |
525 | inline void | |
526 | __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type) | |
527 | { } | |
528 | ||
529 | template<typename _Alloc> | |
530 | inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two) | |
531 | { | |
532 | typedef allocator_traits<_Alloc> __traits; | |
533 | typedef typename __traits::propagate_on_container_copy_assignment __pocca; | |
534 | __do_alloc_on_copy(__one, __two, __pocca()); | |
535 | } | |
536 | ||
537 | template<typename _Alloc> | |
538 | inline _Alloc __alloc_on_copy(const _Alloc& __a) | |
539 | { | |
540 | typedef allocator_traits<_Alloc> __traits; | |
541 | return __traits::select_on_container_copy_construction(__a); | |
542 | } | |
543 | ||
544 | template<typename _Alloc> | |
545 | inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type) | |
546 | { __one = std::move(__two); } | |
547 | ||
548 | template<typename _Alloc> | |
549 | inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type) | |
550 | { } | |
551 | ||
552 | template<typename _Alloc> | |
553 | inline void __alloc_on_move(_Alloc& __one, _Alloc& __two) | |
554 | { | |
555 | typedef allocator_traits<_Alloc> __traits; | |
556 | typedef typename __traits::propagate_on_container_move_assignment __pocma; | |
557 | __do_alloc_on_move(__one, __two, __pocma()); | |
558 | } | |
559 | ||
560 | template<typename _Alloc> | |
561 | inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type) | |
562 | { | |
563 | using std::swap; | |
564 | swap(__one, __two); | |
565 | } | |
566 | ||
567 | template<typename _Alloc> | |
568 | inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type) | |
569 | { } | |
570 | ||
571 | template<typename _Alloc> | |
572 | inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two) | |
573 | { | |
574 | typedef allocator_traits<_Alloc> __traits; | |
575 | typedef typename __traits::propagate_on_container_swap __pocs; | |
576 | __do_alloc_on_swap(__one, __two, __pocs()); | |
577 | } | |
578 | ||
8175e986 JW |
579 | template<typename _Alloc> |
580 | class __is_copy_insertable_impl | |
581 | { | |
582 | typedef allocator_traits<_Alloc> _Traits; | |
583 | ||
584 | template<typename _Up, typename | |
585 | = decltype(_Traits::construct(std::declval<_Alloc&>(), | |
586 | std::declval<_Up*>(), | |
587 | std::declval<const _Up&>()))> | |
588 | static true_type | |
589 | _M_select(int); | |
590 | ||
591 | template<typename _Up> | |
592 | static false_type | |
593 | _M_select(...); | |
594 | ||
595 | public: | |
b7202baf | 596 | typedef decltype(_M_select<typename _Alloc::value_type>(0)) type; |
8175e986 JW |
597 | }; |
598 | ||
b7202baf | 599 | // true if _Alloc::value_type is CopyInsertable into containers using _Alloc |
8175e986 JW |
600 | template<typename _Alloc> |
601 | struct __is_copy_insertable | |
602 | : __is_copy_insertable_impl<_Alloc>::type | |
603 | { }; | |
604 | ||
605 | // std::allocator<_Tp> just requires CopyConstructible | |
606 | template<typename _Tp> | |
607 | struct __is_copy_insertable<allocator<_Tp>> | |
608 | : is_copy_constructible<_Tp> | |
609 | { }; | |
610 | ||
6d82c562 JW |
611 | // Trait to detect Allocator-like types. |
612 | template<typename _Alloc, typename = void> | |
613 | struct __is_allocator : false_type { }; | |
614 | ||
615 | template<typename _Alloc> | |
616 | struct __is_allocator<_Alloc, | |
617 | __void_t<typename _Alloc::value_type, | |
618 | decltype(std::declval<_Alloc&>().allocate(size_t{}))>> | |
619 | : true_type { }; | |
620 | ||
621 | template<typename _Alloc> | |
622 | using _RequireAllocator | |
623 | = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type; | |
6d82c562 | 624 | |
e8eb60bd JW |
625 | _GLIBCXX_END_NAMESPACE_VERSION |
626 | } // namespace std | |
cf3e6e9f JW |
627 | #endif // C++11 |
628 | #endif // _ALLOC_TRAITS_H |