bit::memory
polymorphic_allocator_deleter.hpp
1 /*****************************************************************************
2  * \file
3  * \brief This header defines an allocator deleter that operates polymorphically
4  * with types, which comes at the cost of storing the size with each
5  * allocation
6  *****************************************************************************/
7 
8 /*
9  The MIT License (MIT)
10 
11  Copyright (c) 2018 Matthew Rodusek
12 
13  Permission is hereby granted, free of charge, to any person obtaining a copy
14  of this software and associated documentation files (the "Software"), to deal
15  in the Software without restriction, including without limitation the rights
16  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  copies of the Software, and to permit persons to whom the Software is
18  furnished to do so, subject to the following conditions:
19 
20  The above copyright notice and this permission notice shall be included in
21  all copies or substantial portions of the Software.
22 
23  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  SOFTWARE.
30 */
31 #ifndef BIT_MEMORY_ADAPTERS_POLYMORPHIC_ALLOCATOR_DELETER_HPP
32 #define BIT_MEMORY_ADAPTERS_POLYMORPHIC_ALLOCATOR_DELETER_HPP
33 
34 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
35 # pragma once
36 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
37 
38 #include "../utilities/ebo_storage.hpp"
39 #include "../utilities/pointer_utilities.hpp" // to_raw_pointer
40 
41 #include "../concepts/AllocatorStorage.hpp"
42 
43 #include "../traits/allocator_traits.hpp"
44 
45 #include <cstddef> // std::size_t, std::ptrdiff_t
46 #include <tuple> // std::forward_as_tuple
47 #include <type_traits> // std::is_reference, std::is_const, etc
48 #include <utility> // std::move
49 #include <memory> // std::pointer_traits
50 
51 namespace bit {
52  namespace memory {
53 
62  template<typename T, typename AllocatorStorage>
64  : private ebo_storage<AllocatorStorage>
65  {
67  using allocator_type = typename AllocatorStorage::allocator_type;
68 
70  using pointer_traits = std::pointer_traits<typename alloc_traits::pointer>;
71 
72  static_assert( !std::is_reference<T>::value, "Unable to delete reference type" );
73  static_assert( !std::is_const<T>::value, "Unable to delete const type" );
74  static_assert( !std::is_void<T>::value, "Unable to delete void type" );
76  "AllocatorStorage must satisfy AllocatorStorage requirements" );
77 
78  //-----------------------------------------------------------------------
79  // Public Member Types
80  //-----------------------------------------------------------------------
81  public:
82 
83  using void_pointer = typename alloc_traits::pointer;
84  using pointer = typename pointer_traits::template rebind<T>;
85  using size_type = typename alloc_traits::size_type;
86  using difference_type = typename alloc_traits::difference_type;
87 
88  //-----------------------------------------------------------------------
89  // Constructor
90  //-----------------------------------------------------------------------
91  public:
92 
97  explicit polymorphic_allocator_deleter( AllocatorStorage storage ) noexcept;
98 
103  polymorphic_allocator_deleter( polymorphic_allocator_deleter&& other ) noexcept = default;
104 
109  polymorphic_allocator_deleter( const polymorphic_allocator_deleter& other ) noexcept = default;
110 
111  //-----------------------------------------------------------------------
112 
113  template<typename U,
114  typename = std::enable_if_t<std::is_convertible<U,T>::value>>
116 
117  template<typename U,
118  typename = std::enable_if_t<std::is_convertible<U,T>::value>>
120 
121  //-----------------------------------------------------------------------
122 
128  operator=( polymorphic_allocator_deleter&& other ) noexcept = default;
129 
134  polymorphic_allocator_deleter& operator=( const polymorphic_allocator_deleter& other ) noexcept = default;
135 
136  //-----------------------------------------------------------------------
137 
138  template<typename U,
139  typename = std::enable_if_t<std::is_convertible<U,T>::value>>
142 
143  template<typename U,
144  typename = std::enable_if_t<std::is_convertible<U,T>::value>>
147 
148  //-----------------------------------------------------------------------
149  // Deallocation
150  //-----------------------------------------------------------------------
151  public:
152 
156  void operator()( pointer p );
157 
158  //-----------------------------------------------------------------------
159  // Private Members
160  //-----------------------------------------------------------------------
161  private:
162 
163  size_type m_size;
164 
165  template<typename,typename> friend class polymorphic_allocator_deleter;
166 
167  //-----------------------------------------------------------------------
168  // Private Observers
169  //-----------------------------------------------------------------------
170  private:
171 
172  AllocatorStorage storage() const noexcept;
173 
174  std::size_t size() const noexcept;
175  };
176 
177 
178  template<typename T, typename AllocatorStorage>
179  class polymorphic_allocator_deleter<T[],AllocatorStorage>
180  : private ebo_storage<AllocatorStorage>
181  {
183  using allocator_type = typename AllocatorStorage::allocator_type;
184 
186  using pointer_traits = std::pointer_traits<typename alloc_traits::pointer>;
187 
188  static_assert( !std::is_reference<T>::value, "Unable to delete reference type" );
189  static_assert( !std::is_const<T>::value, "Unable to delete const type" );
190  static_assert( !std::is_void<T>::value, "Unable to delete void type" );
192  "AllocatorStorage must satisfy AllocatorStorage requirements" );
193 
194  //-----------------------------------------------------------------------
195  // Public Member Types
196  //-----------------------------------------------------------------------
197  public:
198 
199  using void_pointer = typename alloc_traits::pointer;
200  using pointer = typename pointer_traits::template rebind<T>;
201  using size_type = typename alloc_traits::size_type;
202  using difference_type = typename alloc_traits::difference_type;
203 
204  //-----------------------------------------------------------------------
205  // Constructor
206  //-----------------------------------------------------------------------
207  public:
208 
213  polymorphic_allocator_deleter( AllocatorStorage storage,
214  size_type size ) noexcept;
215 
220  polymorphic_allocator_deleter( polymorphic_allocator_deleter&& other ) noexcept = default;
221 
226  polymorphic_allocator_deleter( const polymorphic_allocator_deleter& other ) noexcept = default;
227 
228  // polymorphic conversions of arrays would be UB
229 
230  //-----------------------------------------------------------------------
231 
237  operator=( polymorphic_allocator_deleter&& other ) noexcept = default;
238 
243  polymorphic_allocator_deleter& operator=( const polymorphic_allocator_deleter& other ) noexcept = default;
244 
245  //-----------------------------------------------------------------------
246  // Deallocation
247  //-----------------------------------------------------------------------
248  public:
249 
253  void operator()( pointer p );
254 
255  //-----------------------------------------------------------------------
256  // Private Members
257  //-----------------------------------------------------------------------
258  private:
259 
260  size_type m_size;
261  };
262  } // namespace memory
263 } // namespace bit
264 
265 #include "detail/polymorphic_allocator_deleter.inl"
266 
267 #endif /* BIT_MEMORY_ADAPTERS_POLYMORPHIC_ALLOCATOR_DELETER_HPP */
Type trait to determine whether T is a AllocatorStorage.
polymorphic_allocator_deleter & operator=(polymorphic_allocator_deleter &&other) noexcept=default
Move-assigns an polymorphic_allocator_deleter from an existing one.
The allocator_traits class template provides a standardized way to access allocator functionality...
void operator()(pointer p)
Deletes the underlying pointer p.
A deleter for bit::memory allocators that allows for polymorphic conversions, at the cost of storing ...
A utility class used for leveraging empty-base optimization for a generic sequence of types...
Definition: ebo_storage.hpp:62