Line data Source code
1 : // Allocator traits -*- C++ -*-
2 :
3 : // Copyright (C) 2011-2014 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 : namespace std _GLIBCXX_VISIBILITY(default)
40 : {
41 : _GLIBCXX_BEGIN_NAMESPACE_VERSION
42 :
43 : template<typename _Alloc, typename _Tp>
44 : class __alloctr_rebind_helper
45 : {
46 : template<typename _Alloc2, typename _Tp2>
47 : static constexpr true_type
48 : _S_chk(typename _Alloc2::template rebind<_Tp2>::other*);
49 :
50 : template<typename, typename>
51 : static constexpr false_type
52 : _S_chk(...);
53 :
54 : public:
55 : using __type = decltype(_S_chk<_Alloc, _Tp>(nullptr));
56 : };
57 :
58 : template<typename _Alloc, typename _Tp,
59 : bool = __alloctr_rebind_helper<_Alloc, _Tp>::__type::value>
60 : struct __alloctr_rebind;
61 :
62 : template<typename _Alloc, typename _Tp>
63 : struct __alloctr_rebind<_Alloc, _Tp, true>
64 : {
65 : typedef typename _Alloc::template rebind<_Tp>::other __type;
66 : };
67 :
68 : template<template<typename, typename...> class _Alloc, typename _Tp,
69 : typename _Up, typename... _Args>
70 : struct __alloctr_rebind<_Alloc<_Up, _Args...>, _Tp, false>
71 : {
72 : typedef _Alloc<_Tp, _Args...> __type;
73 : };
74 :
75 : /**
76 : * @brief Uniform interface to all allocator types.
77 : * @ingroup allocators
78 : */
79 : template<typename _Alloc>
80 : struct allocator_traits
81 : {
82 : /// The allocator type
83 : typedef _Alloc allocator_type;
84 : /// The allocated type
85 : typedef typename _Alloc::value_type value_type;
86 :
87 : #define _GLIBCXX_ALLOC_TR_NESTED_TYPE(_NTYPE, _ALT) \
88 : private: \
89 : template<typename _Tp> \
90 : static typename _Tp::_NTYPE _S_##_NTYPE##_helper(_Tp*); \
91 : static _ALT _S_##_NTYPE##_helper(...); \
92 : typedef decltype(_S_##_NTYPE##_helper((_Alloc*)0)) __##_NTYPE; \
93 : public:
94 :
95 : _GLIBCXX_ALLOC_TR_NESTED_TYPE(pointer, value_type*)
96 :
97 : /**
98 : * @brief The allocator's pointer type.
99 : *
100 : * @c Alloc::pointer if that type exists, otherwise @c value_type*
101 : */
102 : typedef __pointer pointer;
103 :
104 : _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_pointer,
105 : typename pointer_traits<pointer>::template rebind<const value_type>)
106 :
107 : /**
108 : * @brief The allocator's const pointer type.
109 : *
110 : * @c Alloc::const_pointer if that type exists, otherwise
111 : * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
112 : */
113 : typedef __const_pointer const_pointer;
114 :
115 : _GLIBCXX_ALLOC_TR_NESTED_TYPE(void_pointer,
116 : typename pointer_traits<pointer>::template rebind<void>)
117 :
118 : /**
119 : * @brief The allocator's void pointer type.
120 : *
121 : * @c Alloc::void_pointer if that type exists, otherwise
122 : * <tt> pointer_traits<pointer>::rebind<void> </tt>
123 : */
124 : typedef __void_pointer void_pointer;
125 :
126 : _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_void_pointer,
127 : typename pointer_traits<pointer>::template rebind<const void>)
128 :
129 : /**
130 : * @brief The allocator's const void pointer type.
131 : *
132 : * @c Alloc::const_void_pointer if that type exists, otherwise
133 : * <tt> pointer_traits<pointer>::rebind<const void> </tt>
134 : */
135 : typedef __const_void_pointer const_void_pointer;
136 :
137 : _GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type,
138 : typename pointer_traits<pointer>::difference_type)
139 :
140 : /**
141 : * @brief The allocator's difference type
142 : *
143 : * @c Alloc::difference_type if that type exists, otherwise
144 : * <tt> pointer_traits<pointer>::difference_type </tt>
145 : */
146 : typedef __difference_type difference_type;
147 :
148 : _GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type,
149 : typename make_unsigned<difference_type>::type)
150 :
151 : /**
152 : * @brief The allocator's size type
153 : *
154 : * @c Alloc::size_type if that type exists, otherwise
155 : * <tt> make_unsigned<difference_type>::type </tt>
156 : */
157 : typedef __size_type size_type;
158 :
159 : _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment,
160 : false_type)
161 :
162 : /**
163 : * @brief How the allocator is propagated on copy assignment
164 : *
165 : * @c Alloc::propagate_on_container_copy_assignment if that type exists,
166 : * otherwise @c false_type
167 : */
168 : typedef __propagate_on_container_copy_assignment
169 : propagate_on_container_copy_assignment;
170 :
171 : _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment,
172 : false_type)
173 :
174 : /**
175 : * @brief How the allocator is propagated on move assignment
176 : *
177 : * @c Alloc::propagate_on_container_move_assignment if that type exists,
178 : * otherwise @c false_type
179 : */
180 : typedef __propagate_on_container_move_assignment
181 : propagate_on_container_move_assignment;
182 :
183 : _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
184 : false_type)
185 :
186 : /**
187 : * @brief How the allocator is propagated on swap
188 : *
189 : * @c Alloc::propagate_on_container_swap if that type exists,
190 : * otherwise @c false_type
191 : */
192 : typedef __propagate_on_container_swap propagate_on_container_swap;
193 :
194 : #undef _GLIBCXX_ALLOC_TR_NESTED_TYPE
195 :
196 : template<typename _Tp>
197 : using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;
198 : template<typename _Tp>
199 : using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
200 :
201 : private:
202 : template<typename _Alloc2>
203 : struct __allocate_helper
204 : {
205 : template<typename _Alloc3,
206 : typename = decltype(std::declval<_Alloc3*>()->allocate(
207 : std::declval<size_type>(),
208 : std::declval<const_void_pointer>()))>
209 : static true_type __test(int);
210 :
211 : template<typename>
212 : static false_type __test(...);
213 :
214 : using type = decltype(__test<_Alloc>(0));
215 : };
216 :
217 : template<typename _Alloc2>
218 : using __has_allocate = typename __allocate_helper<_Alloc2>::type;
219 :
220 : template<typename _Alloc2,
221 : typename = _Require<__has_allocate<_Alloc2>>>
222 : static pointer
223 : _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint)
224 : { return __a.allocate(__n, __hint); }
225 :
226 : template<typename _Alloc2, typename _UnusedHint,
227 : typename = _Require<__not_<__has_allocate<_Alloc2>>>>
228 : static pointer
229 : _S_allocate(_Alloc2& __a, size_type __n, _UnusedHint)
230 : { return __a.allocate(__n); }
231 :
232 : template<typename _Tp, typename... _Args>
233 : struct __construct_helper
234 : {
235 : template<typename _Alloc2,
236 : typename = decltype(std::declval<_Alloc2*>()->construct(
237 : std::declval<_Tp*>(), std::declval<_Args>()...))>
238 : static true_type __test(int);
239 :
240 : template<typename>
241 : static false_type __test(...);
242 :
243 : using type = decltype(__test<_Alloc>(0));
244 : };
245 :
246 : template<typename _Tp, typename... _Args>
247 : using __has_construct
248 : = typename __construct_helper<_Tp, _Args...>::type;
249 :
250 : template<typename _Tp, typename... _Args>
251 : static _Require<__has_construct<_Tp, _Args...>>
252 120 : _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
253 120 : { __a.construct(__p, std::forward<_Args>(__args)...); }
254 :
255 : template<typename _Tp, typename... _Args>
256 : static
257 : _Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
258 : is_constructible<_Tp, _Args...>>>
259 : _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
260 : { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
261 :
262 : template<typename _Tp>
263 : struct __destroy_helper
264 : {
265 : template<typename _Alloc2,
266 : typename = decltype(std::declval<_Alloc2*>()->destroy(
267 : std::declval<_Tp*>()))>
268 : static true_type __test(int);
269 :
270 : template<typename>
271 : static false_type __test(...);
272 :
273 : using type = decltype(__test<_Alloc>(0));
274 : };
275 :
276 : template<typename _Tp>
277 : using __has_destroy = typename __destroy_helper<_Tp>::type;
278 :
279 : template<typename _Tp>
280 : static _Require<__has_destroy<_Tp>>
281 36 : _S_destroy(_Alloc& __a, _Tp* __p)
282 36 : { __a.destroy(__p); }
283 :
284 : template<typename _Tp>
285 : static _Require<__not_<__has_destroy<_Tp>>>
286 : _S_destroy(_Alloc&, _Tp* __p)
287 : { __p->~_Tp(); }
288 :
289 : template<typename _Alloc2>
290 : struct __maxsize_helper
291 : {
292 : template<typename _Alloc3,
293 : typename = decltype(std::declval<_Alloc3*>()->max_size())>
294 : static true_type __test(int);
295 :
296 : template<typename>
297 : static false_type __test(...);
298 :
299 : using type = decltype(__test<_Alloc2>(0));
300 : };
301 :
302 : template<typename _Alloc2>
303 : using __has_max_size = typename __maxsize_helper<_Alloc2>::type;
304 :
305 : template<typename _Alloc2,
306 : typename = _Require<__has_max_size<_Alloc2>>>
307 : static size_type
308 161 : _S_max_size(_Alloc2& __a, int)
309 161 : { return __a.max_size(); }
310 :
311 : template<typename _Alloc2,
312 : typename = _Require<__not_<__has_max_size<_Alloc2>>>>
313 : static size_type
314 : _S_max_size(_Alloc2&, ...)
315 : { return __gnu_cxx::__numeric_traits<size_type>::__max; }
316 :
317 : template<typename _Alloc2>
318 : struct __select_helper
319 : {
320 : template<typename _Alloc3, typename
321 : = decltype(std::declval<_Alloc3*>()
322 : ->select_on_container_copy_construction())>
323 : static true_type __test(int);
324 :
325 : template<typename>
326 : static false_type __test(...);
327 :
328 : using type = decltype(__test<_Alloc2>(0));
329 : };
330 :
331 : template<typename _Alloc2>
332 : using __has_soccc = typename __select_helper<_Alloc2>::type;
333 :
334 : template<typename _Alloc2,
335 : typename = _Require<__has_soccc<_Alloc2>>>
336 : static _Alloc2
337 : _S_select(_Alloc2& __a, int)
338 : { return __a.select_on_container_copy_construction(); }
339 :
340 : template<typename _Alloc2,
341 : typename = _Require<__not_<__has_soccc<_Alloc2>>>>
342 : static _Alloc2
343 42 : _S_select(_Alloc2& __a, ...)
344 42 : { return __a; }
345 :
346 : public:
347 :
348 : /**
349 : * @brief Allocate memory.
350 : * @param __a An allocator.
351 : * @param __n The number of objects to allocate space for.
352 : *
353 : * Calls @c a.allocate(n)
354 : */
355 : static pointer
356 163 : allocate(_Alloc& __a, size_type __n)
357 163 : { return __a.allocate(__n); }
358 :
359 : /**
360 : * @brief Allocate memory.
361 : * @param __a An allocator.
362 : * @param __n The number of objects to allocate space for.
363 : * @param __hint Aid to locality.
364 : * @return Memory of suitable size and alignment for @a n objects
365 : * of type @c value_type
366 : *
367 : * Returns <tt> a.allocate(n, hint) </tt> if that expression is
368 : * well-formed, otherwise returns @c a.allocate(n)
369 : */
370 : static pointer
371 : allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
372 : { return _S_allocate(__a, __n, __hint); }
373 :
374 : /**
375 : * @brief Deallocate memory.
376 : * @param __a An allocator.
377 : * @param __p Pointer to the memory to deallocate.
378 : * @param __n The number of objects space was allocated for.
379 : *
380 : * Calls <tt> a.deallocate(p, n) </tt>
381 : */
382 163 : static void deallocate(_Alloc& __a, pointer __p, size_type __n)
383 163 : { __a.deallocate(__p, __n); }
384 :
385 : /**
386 : * @brief Construct an object of type @a _Tp
387 : * @param __a An allocator.
388 : * @param __p Pointer to memory of suitable size and alignment for Tp
389 : * @param __args Constructor arguments.
390 : *
391 : * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
392 : * if that expression is well-formed, otherwise uses placement-new
393 : * to construct an object of type @a _Tp at location @a __p from the
394 : * arguments @a __args...
395 : */
396 : template<typename _Tp, typename... _Args>
397 120 : static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
398 : -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
399 120 : { _S_construct(__a, __p, std::forward<_Args>(__args)...); }
400 :
401 : /**
402 : * @brief Destroy an object of type @a _Tp
403 : * @param __a An allocator.
404 : * @param __p Pointer to the object to destroy
405 : *
406 : * Calls @c __a.destroy(__p) if that expression is well-formed,
407 : * otherwise calls @c __p->~_Tp()
408 : */
409 : template <class _Tp>
410 36 : static void destroy(_Alloc& __a, _Tp* __p)
411 36 : { _S_destroy(__a, __p); }
412 :
413 : /**
414 : * @brief The maximum supported allocation size
415 : * @param __a An allocator.
416 : * @return @c __a.max_size() or @c numeric_limits<size_type>::max()
417 : *
418 : * Returns @c __a.max_size() if that expression is well-formed,
419 : * otherwise returns @c numeric_limits<size_type>::max()
420 : */
421 161 : static size_type max_size(const _Alloc& __a) noexcept
422 161 : { return _S_max_size(__a, 0); }
423 :
424 : /**
425 : * @brief Obtain an allocator to use when copying a container.
426 : * @param __rhs An allocator.
427 : * @return @c __rhs.select_on_container_copy_construction() or @a __rhs
428 : *
429 : * Returns @c __rhs.select_on_container_copy_construction() if that
430 : * expression is well-formed, otherwise returns @a __rhs
431 : */
432 : static _Alloc
433 42 : select_on_container_copy_construction(const _Alloc& __rhs)
434 42 : { return _S_select(__rhs, 0); }
435 : };
436 :
437 : template<typename _Alloc>
438 : inline void
439 : __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
440 : { __one = __two; }
441 :
442 : template<typename _Alloc>
443 : inline void
444 0 : __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
445 0 : { }
446 :
447 : template<typename _Alloc>
448 0 : inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
449 : {
450 : typedef allocator_traits<_Alloc> __traits;
451 : typedef typename __traits::propagate_on_container_copy_assignment __pocca;
452 0 : __do_alloc_on_copy(__one, __two, __pocca());
453 0 : }
454 :
455 : template<typename _Alloc>
456 : inline _Alloc __alloc_on_copy(const _Alloc& __a)
457 : {
458 : typedef allocator_traits<_Alloc> __traits;
459 : return __traits::select_on_container_copy_construction(__a);
460 : }
461 :
462 : template<typename _Alloc>
463 2 : inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
464 2 : { __one = std::move(__two); }
465 :
466 : template<typename _Alloc>
467 : inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
468 : { }
469 :
470 : template<typename _Alloc>
471 2 : inline void __alloc_on_move(_Alloc& __one, _Alloc& __two)
472 : {
473 : typedef allocator_traits<_Alloc> __traits;
474 : typedef typename __traits::propagate_on_container_move_assignment __pocma;
475 2 : __do_alloc_on_move(__one, __two, __pocma());
476 2 : }
477 :
478 : template<typename _Alloc>
479 : inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
480 : {
481 : using std::swap;
482 : swap(__one, __two);
483 : }
484 :
485 : template<typename _Alloc>
486 0 : inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
487 0 : { }
488 :
489 : template<typename _Alloc>
490 0 : inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two)
491 : {
492 : typedef allocator_traits<_Alloc> __traits;
493 : typedef typename __traits::propagate_on_container_swap __pocs;
494 0 : __do_alloc_on_swap(__one, __two, __pocs());
495 0 : }
496 :
497 : template<typename _Alloc>
498 : class __is_copy_insertable_impl
499 : {
500 : typedef allocator_traits<_Alloc> _Traits;
501 :
502 : template<typename _Up, typename
503 : = decltype(_Traits::construct(std::declval<_Alloc&>(),
504 : std::declval<_Up*>(),
505 : std::declval<const _Up&>()))>
506 : static true_type
507 : _M_select(int);
508 :
509 : template<typename _Up>
510 : static false_type
511 : _M_select(...);
512 :
513 : public:
514 : typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
515 : };
516 :
517 : // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
518 : template<typename _Alloc>
519 : struct __is_copy_insertable
520 : : __is_copy_insertable_impl<_Alloc>::type
521 : { };
522 :
523 : // std::allocator<_Tp> just requires CopyConstructible
524 : template<typename _Tp>
525 : struct __is_copy_insertable<allocator<_Tp>>
526 : : is_copy_constructible<_Tp>
527 : { };
528 :
529 : _GLIBCXX_END_NAMESPACE_VERSION
530 : } // namespace std
531 :
532 : #endif
533 : #endif
|