Backport
memory.hpp
Go to the documentation of this file.
1 
7 /*
8  The MIT License (MIT)
9 
10  Copyright (c) 2020 Matthew Rodusek All rights reserved.
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 BPSTD_MEMORY_HPP
31 #define BPSTD_MEMORY_HPP
32 
33 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
34 # pragma once
35 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
36 
37 #include "detail/config.hpp"
38 #include "type_traits.hpp" // conditional_t, void_t
39 #include "utility.hpp" // forward
40 
41 #include <memory> // std::unique_ptr
42 #include <cstddef> // std::size_t
43 #include <type_traits> // std::declval
44 
45 BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
46 
47 namespace bpstd {
48 
49  namespace detail {
50  template <typename T>
51  struct make_unique_result
52  {
53  using object = T;
54  };
55  template <typename T>
56  struct make_unique_result<T[]>
57  {
58  using unbounded_array = T[];
59  };
60  template <typename T, std::size_t N>
61  struct make_unique_result<T[N]>
62  {
63  using bounded_array = T[N];
64  };
65  }
66 
76  template <typename T, typename...Args>
77  std::unique_ptr<typename detail::make_unique_result<T>::object>
78  make_unique(Args&&...args);
79 
88  template <typename T>
89  std::unique_ptr<typename detail::make_unique_result<T>::unbounded_array>
90  make_unique(std::size_t size);
91 
92  // Construction of arrays of known bound is disallowed
93  template <typename T>
94  std::unique_ptr<typename detail::make_unique_result<T>::bounded_array>
95  make_unique() = delete;
96 
107  template <typename T>
108  std::unique_ptr<typename detail::make_unique_result<T>::object>
110 
121  template <typename T>
122  std::unique_ptr<typename detail::make_unique_result<T>::unbounded_array>
123  make_unique_for_overwrite(std::size_t size);
124 
125  // Construction of arrays of known bound is disallowed
126  template <typename T>
127  std::unique_ptr<typename detail::make_unique_result<T>::bounded_array>
128  make_unique_for_overwrite() = delete;
129 
130  //----------------------------------------------------------------------------
131 
132  namespace detail {
133 
134  template <typename T, typename = void>
135  struct has_to_address : false_type{};
136 
137  template <typename T>
138  struct has_to_address<T,void_t<decltype(std::pointer_traits<T>::to_address(std::declval<const T&>()))>>
139  : true_type{};
140 
141  //--------------------------------------------------------------------------
142 
143  template <bool, typename T>
144  struct operator_deref
145  {
146  using type = decltype(std::declval<const T&>().operator->());
147  };
148 
149  template <typename T>
150  struct operator_deref<true, T>{};
151 
152  //--------------------------------------------------------------------------
153 
154  template <typename T, typename = void>
155  struct to_address_result
156  : operator_deref<std::is_pointer<remove_cvref_t<T>>::value, T>{};
157 
158  template <typename T>
159  struct to_address_result<T,void_t<decltype(std::pointer_traits<T>::to_address(std::declval<const T&>()))>>
160  {
161  using type = decltype(std::pointer_traits<T>::to_address(std::declval<const T&>()));
162  };
163 
164  template <typename T>
165  using to_address_result_t = typename to_address_result<T>::type;
166 
167  } // namespace detail
168 
175  template <typename T>
176  constexpr T* to_address(T* p) noexcept;
177  template <typename T>
178  constexpr detail::to_address_result_t<T> to_address(const T& p) noexcept;
180 
181 } // namespace bpstd
182 
183 template <typename T, typename...Args>
184 inline BPSTD_INLINE_VISIBILITY
185 std::unique_ptr<typename bpstd::detail::make_unique_result<T>::object>
186  bpstd::make_unique(Args&&...args)
187 {
188  return std::unique_ptr<T>{new T(bpstd::forward<Args>(args)...)};
189 }
190 
191 template <typename T>
192 inline BPSTD_INLINE_VISIBILITY
193 std::unique_ptr<typename bpstd::detail::make_unique_result<T>::unbounded_array>
194  bpstd::make_unique(std::size_t size)
195 {
196  return std::unique_ptr<T>{new remove_extent_t<T>[size]()};
197 }
198 
199 template <typename T>
200 inline BPSTD_INLINE_VISIBILITY
201 std::unique_ptr<typename bpstd::detail::make_unique_result<T>::object>
202  bpstd::make_unique_for_overwrite()
203 {
204  return std::unique_ptr<T>{new T};
205 }
206 
207 template <typename T>
208 inline BPSTD_INLINE_VISIBILITY
209 std::unique_ptr<typename bpstd::detail::make_unique_result<T>::unbounded_array>
210  bpstd::make_unique_for_overwrite(std::size_t size)
211 {
212  return std::unique_ptr<T>{new remove_extent_t<T>[size]};
213 }
214 
215 namespace bpstd {
216  namespace detail {
217 
218  template <typename T>
219  inline BPSTD_INLINE_VISIBILITY constexpr
220  auto to_address_impl(const T& p, std::true_type)
221  -> decltype(std::pointer_traits<T>::to_address(std::declval<const T&>()))
222  {
223  return to_address(std::pointer_traits<T>::to_address(p));
224  }
225 
226  template <typename T>
227  inline BPSTD_INLINE_VISIBILITY constexpr
228  auto to_address_impl(const T& p, std::false_type)
229  -> decltype(std::declval<const T&>().operator->())
230  {
231  return to_address(p.operator->());
232  }
233 
234  } // namespace detail
235 } // namespace bpstd
236 
237 template <typename T>
238 inline BPSTD_INLINE_VISIBILITY constexpr
239 T* bpstd::to_address(T* p)
240  noexcept
241 {
242  static_assert(
243  !std::is_function<T>::value,
244  "T* must not be a function pointer"
245  );
246 
247  return p;
248 }
249 
250 template <typename T>
251 inline BPSTD_INLINE_VISIBILITY constexpr
252 bpstd::detail::to_address_result_t<T>
253  bpstd::to_address(const T& p)
254  noexcept
255 {
256  return detail::to_address_impl(p, detail::has_to_address<T>{});
257 }
258 
259 BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
260 
261 #endif /* BPSTD_MEMORY_HPP */
bpstd::to_address
constexpr detail::to_address_result_t< T > to_address(const T &p) noexcept
Converts a pointer-like type to a raw pointer by recursively calling to_address on it.
type_traits.hpp
This header provides definitions from the C++ header <type_traits>
bpstd::size
constexpr auto size(const C &c) -> decltype(c.size())
Gets the size of a container.
bpstd::to_address
constexpr T * to_address(T *p) noexcept
Converts a pointer-like type to a raw pointer by recursively calling to_address on it.
bpstd::make_unique_for_overwrite
std::unique_ptr< typename detail::make_unique_result< T >::object > make_unique_for_overwrite()
Constructs an object of type T through default-initialization and wraps it in a std::unique_ptr.
bpstd::make_unique
std::unique_ptr< typename detail::make_unique_result< T >::object > make_unique(Args &&...args)
Constructs an object of type T and wraps it in a std::unique_ptr.
utility.hpp
This header provides definitions from the C++ header <utility>