//////////////////////////////////////////////////////////////////////////////// /// \file memory.hpp /// /// \brief This header provides definitions from the C++ header //////////////////////////////////////////////////////////////////////////////// /* The MIT License (MIT) Copyright (c) 2020 Matthew Rodusek All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef BPSTD_MEMORY_HPP #define BPSTD_MEMORY_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "detail/config.hpp" #include "type_traits.hpp" // conditional_t, void_t #include "utility.hpp" // forward #include // std::unique_ptr #include // std::size_t #include // std::declval BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE namespace bpstd { namespace detail { template struct make_unique_result { using object = T; }; template struct make_unique_result { using unbounded_array = T[]; }; template struct make_unique_result { using bounded_array = T[N]; }; } /// \brief Constructs an object of type T and wraps it in a std::unique_ptr /// /// Constructs a non-array type T. The arguments args are passed to the /// constructor of T. This overload only participates in overload resolution /// if T is not an array type. /// /// \tparam T the type to construct /// \param args the arguments to forward to T's constructor /// \return the unique_ptr template std::unique_ptr::object> make_unique(Args&&...args); /// \brief Constructs an object of type T[] and wraps it in a std::unique_ptr /// /// Constructs an array of unknown bound T. This overload only participates /// in overload resolution if T is an array of unknown bound. /// /// \tparam T the type to construct /// \param size the size of the array /// \return the unique_ptr template std::unique_ptr::unbounded_array> make_unique(std::size_t size); // Construction of arrays of known bound is disallowed template std::unique_ptr::bounded_array> make_unique() = delete; /// \brief Constructs an object of type T through default-initialization /// and wraps it in a std::unique_ptr /// /// Constructs a non-array type T. This overload only participates in /// overload resolution if T is not an array type. The object is /// default-initialised, which may mean it will need to be overwritten before /// it is legal to be read /// /// \tparam T the type to construct /// \return the unique_ptr template std::unique_ptr::object> make_unique_for_overwrite(); /// \brief Constructs an object of type T[] through default-initialization /// and wraps it in a std::unique_ptr /// /// Constructs an array of unknown bound T. This overload only participates /// in overload resolution if T is an array of unknown bound. The array is /// default-initialised, which may mean it will need to be overwritten before /// it is legal to be read /// /// \tparam T the type to construct /// \return the unique_ptr template std::unique_ptr::unbounded_array> make_unique_for_overwrite(std::size_t size); // Construction of arrays of known bound is disallowed template std::unique_ptr::bounded_array> make_unique_for_overwrite() = delete; //---------------------------------------------------------------------------- namespace detail { template struct has_to_address : false_type{}; template struct has_to_address::to_address(std::declval()))>> : true_type{}; //-------------------------------------------------------------------------- template struct operator_deref { using type = decltype(std::declval().operator->()); }; template struct operator_deref{}; //-------------------------------------------------------------------------- template struct to_address_result : operator_deref>::value, T>{}; template struct to_address_result::to_address(std::declval()))>> { using type = decltype(std::pointer_traits::to_address(std::declval())); }; template using to_address_result_t = typename to_address_result::type; } // namespace detail /// \{ /// \brief Converts a pointer-like type to a raw pointer by recursively /// calling to_address on it /// /// \param p the pointer-like type /// \return the pointer template constexpr T* to_address(T* p) noexcept; template constexpr detail::to_address_result_t to_address(const T& p) noexcept; /// \} } // namespace bpstd template inline BPSTD_INLINE_VISIBILITY std::unique_ptr::object> bpstd::make_unique(Args&&...args) { return std::unique_ptr{new T(bpstd::forward(args)...)}; } template inline BPSTD_INLINE_VISIBILITY std::unique_ptr::unbounded_array> bpstd::make_unique(std::size_t size) { return std::unique_ptr{new remove_extent_t[size]()}; } template inline BPSTD_INLINE_VISIBILITY std::unique_ptr::object> bpstd::make_unique_for_overwrite() { return std::unique_ptr{new T}; } template inline BPSTD_INLINE_VISIBILITY std::unique_ptr::unbounded_array> bpstd::make_unique_for_overwrite(std::size_t size) { return std::unique_ptr{new remove_extent_t[size]}; } namespace bpstd { namespace detail { template inline BPSTD_INLINE_VISIBILITY constexpr auto to_address_impl(const T& p, std::true_type) -> decltype(std::pointer_traits::to_address(std::declval())) { return to_address(std::pointer_traits::to_address(p)); } template inline BPSTD_INLINE_VISIBILITY constexpr auto to_address_impl(const T& p, std::false_type) -> decltype(std::declval().operator->()) { return to_address(p.operator->()); } } // namespace detail } // namespace bpstd template inline BPSTD_INLINE_VISIBILITY constexpr T* bpstd::to_address(T* p) noexcept { static_assert( !std::is_function::value, "T* must not be a function pointer" ); return p; } template inline BPSTD_INLINE_VISIBILITY constexpr bpstd::detail::to_address_result_t bpstd::to_address(const T& p) noexcept { return detail::to_address_impl(p, detail::has_to_address{}); } BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE #endif /* BPSTD_MEMORY_HPP */