// Copyright (c) 2018-2025 Jean-Louis Leroy // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_OPENMETHOD_INTEROP_UNIQUE_PTR_HPP #define BOOST_OPENMETHOD_INTEROP_UNIQUE_PTR_HPP #include #include namespace boost::openmethod { //! Specialize virtual_traits for std::unique_ptr by value. //! //! @tparam Class A class type, possibly cv-qualified. //! @tparam Registry A @ref registry. template struct virtual_traits, Registry> { //! `Class`, stripped from cv-qualifiers. using virtual_type = std::remove_cv_t; //! Return a reference to a non-modifiable `Class` object. //! @param arg A reference to a `std::unique_ptr`. //! @return A reference to the object pointed to. static auto peek(const std::unique_ptr& arg) -> const Class& { return *arg; } //! Cast to a type. //! //! Cast a reference to the managed object, using `static_cast` if possible, //! and `Registry::rtti::dynamic_cast_ref` otherwise. If the cast succeeds, //! transfer ownership to a `std::unique_ptr` to the target type, and return //! it. //! //! @tparam Derived A xvalue reference to a `std::unique_ptr`. //! @param obj A xvalue reference to a `std::unique_ptr`. //! @return A `std::unique_ptr`. template static auto cast(std::unique_ptr&& ptr) { if constexpr (detail::requires_dynamic_cast) { auto p = &Registry::rtti::template dynamic_cast_ref< typename Derived::element_type&>(*ptr); ptr.release(); return Derived(p); } else { auto p = &static_cast(*ptr); ptr.release(); return Derived(p); } } //! Rebind to a different element type. //! //! @tparam Other The new element type. template using rebind = std::unique_ptr; }; //! Alias for a `virtual_ptr>`. template using unique_virtual_ptr = virtual_ptr, Registry>; //! Create a new object and return a `unique_virtual_ptr` to it. //! //! Create an object using `std::make_unique`, and return a @ref //! unique_virtual_ptr pointing to it. Since the exact class of the object is //! known, the `virtual_ptr` is created using @ref final_virtual_ptr. //! //! `Class` is _not_ required to be a polymorphic class. //! //! @tparam Class The class of the object to create. //! @tparam Registry A @ref registry. //! @tparam T Types of the arguments to pass to the constructor of `Class`. //! @param args Arguments to pass to the constructor of `Class`. //! @return A `unique_virtual_ptr` pointing to a newly //! created object of type `Class`. template< class Class, class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T> inline auto make_unique_virtual(T&&... args) { return final_virtual_ptr( std::make_unique(std::forward(args)...)); } namespace aliases { using boost::openmethod::make_unique_virtual; using boost::openmethod::unique_virtual_ptr; } // namespace aliases } // namespace boost::openmethod #endif