bit::memory
allocator_traits.hpp
1 /*****************************************************************************
2  * \file
3  * \brief This header contains the trait type \c allocator_traits that
4  * determines or infers default values for the Allocator concept
5  *****************************************************************************/
6 
7 /*
8  The MIT License (MIT)
9 
10  Copyright (c) 2018 Matthew Rodusek
11 
12  Permission is hereby granted, free of charge, to any person obtaining a copy
13  of this software and associated documentation files (the "Software"), to deal
14  in the Software without restriction, including without limitation the rights
15  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  copies of the Software, and to permit persons to whom the Software is
17  furnished to do so, subject to the following conditions:
18 
19  The above copyright notice and this permission notice shall be included in
20  all copies or substantial portions of the Software.
21 
22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  SOFTWARE.
29 */
30 #ifndef BIT_MEMORY_TRAITS_ALLOCATOR_TRAITS_HPP
31 #define BIT_MEMORY_TRAITS_ALLOCATOR_TRAITS_HPP
32 
33 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
34 # pragma once
35 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
36 
37 #include "../utilities/allocator_info.hpp" // allocator_info
38 #include "../utilities/errors.hpp" // get_out_of_memory_handler
39 #include "../utilities/macros.hpp" // BIT_MEMORY_UNUSED
40 #include "../utilities/owner.hpp" // owner
41 #include "../utilities/pointer_utilities.hpp" // to_raw_pointer
42 #include "../utilities/uninitialized_storage.hpp" // destroy_at, etc
43 
44 #include "../concepts/Allocator.hpp" // is_allocator, allocator_has_allocate,
45 
46 #include <type_traits> // std::true_type, std::false_type, etc
47 #include <cstddef> // std::size_t, std::ptrdiff_t
48 #include <limits> // std::numeric_limits
49 #include <memory> // std::addressof. std::pointer_traits
50 #include <typeinfo> // std::type_info
51 #include <utility> // std::move, std::forward
52 
53 namespace bit {
54  namespace memory {
55  namespace detail {
56 
57  template<typename Allocator, typename T, typename=void>
58  struct allocator_pointer_rebind
59  {
60  using type = typename std::pointer_traits<allocator_pointer_t<Allocator>>::template rebind<T>;
61  };
62 
63  template<typename Allocator, typename T>
64  struct allocator_pointer_rebind<Allocator,T,void_t<typename Allocator::template pointer_rebind<T>>>
65  {
66  using type = typename Allocator::template pointer_rebind<T>;
67  };
68 
69  } // namespace detail
70 
80  template<typename Allocator>
82  {
83  static_assert( is_allocator<Allocator>::value,
84  "Allocator must be an Allocator" );
85 
86  template<typename T>
87  struct negation : std::integral_constant<bool,!T::value>{};
88 
89  //-----------------------------------------------------------------------
90  // Public Members
91  //-----------------------------------------------------------------------
92  public:
93 
94  // aliases
95  using pointer = allocator_pointer_t<Allocator>;
96  using const_pointer = allocator_const_pointer_t<Allocator>;
97  using size_type = allocator_size_type_t<Allocator>;
98  using difference_type = allocator_difference_type_t<Allocator>;
99 
103  template<typename T>
104  using pointer_rebind = typename detail::allocator_pointer_rebind<Allocator,T>::type;
105 
106  // properties
111  using uses_pretty_pointers = negation<std::is_same<void*,pointer_rebind<void>>>;
112 
113  private:
114 
115  template<typename Pointer>
116  static constexpr bool is_typed_pointer = std::is_same<typename std::pointer_traits<Pointer>::template rebind<void>,
117  pointer>::value;
118 
119  //-----------------------------------------------------------------------
120  // Allocation
121  //-----------------------------------------------------------------------
122  public:
123 
135  static pointer try_allocate( Allocator& alloc,
136  size_type size,
137  size_type align ) noexcept;
138  static pointer try_allocate( Allocator& alloc,
139  const_pointer hint,
140  size_type size,
141  size_type align ) noexcept;
143 
144  //-----------------------------------------------------------------------
145 
158  static pointer allocate( Allocator& alloc,
159  size_type size,
160  size_type align );
161  static pointer allocate( Allocator& alloc,
162  const_pointer hint,
163  size_type size,
164  size_type align );
166 
183  static bool expand( Allocator& alloc,
184  pointer p,
185  size_type new_size );
187 
188  //-----------------------------------------------------------------------
189  // Deallocation
190  //-----------------------------------------------------------------------
191  public:
192 
199  static void deallocate( Allocator& alloc, pointer p, size_type size );
200 
206  template<typename U = Allocator, typename = std::enable_if<can_truncate_deallocations::value>>
207  static void deallocate_all( Allocator& alloc );
208 
209  //-----------------------------------------------------------------------
210  // Constructions
211  //-----------------------------------------------------------------------
212  public:
213 
214  // Unfortunately, MSVC is unable to compile 'pointer_rebind<T>' as a
215  // return type, with the definition written out-of-line -- so the following
216  // is expanded in place.
217  //
218  // gcc/clang accept 'pointer_rebind<T>' with its expansion:
219  // typename bit::memory::allocator_traits<Allocator>::template pointer_rebind<T>
220  // MSVC does not, but curiously will accept the ever-verbose expansion
221  // of what 'pointer_rebind<T>' aliases.
222 
230  template<typename T, typename...Args>
231  static void construct( Allocator& alloc, void* p, Args&&...args );
232 
242  template<typename T, typename...Args>
243  static typename detail::allocator_pointer_rebind<Allocator,T>::type
244  make( Allocator& alloc, Args&&...args );
245 
246  //-----------------------------------------------------------------------
247 
258  template<typename T>
259  static typename std::pointer_traits<pointer>::template rebind<T>
260  make_array( Allocator& alloc, size_type n );
261  template<typename T>
262  static typename std::pointer_traits<pointer>::template rebind<T>
263  make_array( Allocator& alloc, size_type n, const T& copy );
265 
266  //-----------------------------------------------------------------------
267  // Destruction
268  //-----------------------------------------------------------------------
269  public:
270 
275  template<typename T>
276  static void destroy( Allocator& alloc, T* p );
277 
298  template<typename Pointer,
299  typename=std::enable_if_t<is_typed_pointer<Pointer>>>
300  static void dispose( Allocator& alloc, const Pointer& p );
301 
322  template<typename Pointer,
323  typename=std::enable_if_t<is_typed_pointer<Pointer>>>
324  static void dispose_array( Allocator& alloc, const Pointer& p, size_type n );
325 
326  //-----------------------------------------------------------------------
327  // Observers
328  //-----------------------------------------------------------------------
329  public:
330 
341  size_type recommended_allocation_size( const Allocator& alloc,
342  size_type requested );
343 
344  //-----------------------------------------------------------------------
345 
356  static bool owns( const Allocator& alloc, const_pointer p ) noexcept;
357 
369  static allocator_info info( const Allocator& alloc ) noexcept;
370 
371  //-----------------------------------------------------------------------
372  // Conversion
373  //-----------------------------------------------------------------------
374  public:
375 
385  template<typename T>
386  static typename std::pointer_traits<pointer>::template rebind<T>
387  pointer_to( Allocator& alloc, T& x ) noexcept;
388 
399  template<typename Pointer,
400  typename=std::enable_if_t<is_typed_pointer<Pointer>>>
401  static typename std::pointer_traits<Pointer>::element_type*
402  to_raw_pointer( Allocator& alloc,
403  const Pointer& p ) noexcept;
404 
405  //-----------------------------------------------------------------------
406  // Capacity
407  //-----------------------------------------------------------------------
408  public:
409 
417  static bool is_unbounded( const Allocator& alloc ) noexcept;
418 
419  //-----------------------------------------------------------------------
420 
431  static size_type max_size( const Allocator& alloc ) noexcept;
432 
439  static size_type min_size( const Allocator& alloc ) noexcept;
440  };
441  } // namespace memory
442 } // namespace bit
443 
444 #include "detail/allocator_traits.inl"
445 
446 #endif /* BIT_MEMORY_TRAITS_ALLOCATOR_TRAITS_HPP */
typename detail::allocator_pointer_rebind< Allocator, T >::type pointer_rebind
Rebinds a pointer to the new pointer type.
Type-trait to determine whether T has a &#39;deallocate_all&#39; function.
Definition: Allocator.hpp:586
Type-trait to determine the default alignment of the given T.
Definition: Allocator.hpp:774
The allocator_traits class template provides a standardized way to access allocator functionality...
Type-trait to determine whether T satisfies the minimum requirements to be an Allocator.
Definition: Allocator.hpp:830
Type-trait to determine the maximum alignment of the given T.
Definition: Allocator.hpp:792
Type-trait to determine whether T has an &#39;owns&#39; function.
Definition: Allocator.hpp:684
This type is used to hold the generic information for a given allocator.