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