File Coverage

/usr/include/c++/5/bits/alloc_traits.h
Criterion Covered Total %
statement 8 8 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 8 8 100.0


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