libstdc++
bits/alloc_traits.h
Go to the documentation of this file.
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>
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>
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  _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
253  { __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  _S_destroy(_Alloc& __a, _Tp* __p)
282  { __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  _S_max_size(_Alloc2& __a, int)
309  { 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*>()
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  _S_select(_Alloc2& __a, ...)
344  { 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  allocate(_Alloc& __a, size_type __n)
357  { 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  static void deallocate(_Alloc& __a, pointer __p, size_type __n)
383  { __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  static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
398  -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
399  { _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  static void destroy(_Alloc& __a, _Tp* __p)
411  { _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  static size_type max_size(const _Alloc& __a) noexcept
422  { 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
434  { 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  __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
445  { }
446 
447  template<typename _Alloc>
448  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  __do_alloc_on_copy(__one, __two, __pocca());
453  }
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  inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
464  { __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  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  __do_alloc_on_move(__one, __two, __pocma());
476  }
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  inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
487  { }
488 
489  template<typename _Alloc>
490  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  __do_alloc_on_swap(__one, __two, __pocs());
495  }
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
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:101
__void_pointer void_pointer
The allocator's void pointer type.
static auto construct(_Alloc &__a, _Tp *__p, _Args &&...__args) -> decltype(_S_construct(__a, __p, std::forward< _Args >(__args)...))
Construct an object of type _Tp.
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:76
static void destroy(_Alloc &__a, _Tp *__p)
Destroy an object of type _Tp.
Uniform interface to all pointer-like types.
Definition: ptr_traits.h:132
__difference_type difference_type
The allocator's difference type.
Uniform interface to all allocator types.
__const_pointer const_pointer
The allocator's const pointer type.
ISO C++ entities toplevel namespace is std.
__propagate_on_container_copy_assignment propagate_on_container_copy_assignment
How the allocator is propagated on copy assignment.
static _Alloc select_on_container_copy_construction(const _Alloc &__rhs)
Obtain an allocator to use when copying a container.
_Alloc::value_type value_type
The allocated type.
static pointer allocate(_Alloc &__a, size_type __n, const_void_pointer __hint)
Allocate memory.
__size_type size_type
The allocator's size type.
__pointer pointer
The allocator's pointer type.
__const_void_pointer const_void_pointer
The allocator's const void pointer type.
static void deallocate(_Alloc &__a, pointer __p, size_type __n)
Deallocate memory.
__propagate_on_container_swap propagate_on_container_swap
How the allocator is propagated on swap.
void swap(_Tp &, _Tp &) noexcept(__and_< is_nothrow_move_constructible< _Tp >, is_nothrow_move_assignable< _Tp >>::value)
Swaps two values.
Definition: move.h:166
static size_type max_size(const _Alloc &__a) noexcept
The maximum supported allocation size.
_Alloc allocator_type
The allocator type.
static pointer allocate(_Alloc &__a, size_type __n)
Allocate memory.
__propagate_on_container_move_assignment propagate_on_container_move_assignment
How the allocator is propagated on move assignment.