| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- // 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 <boost/openmethod/core.hpp>
- #include <memory>
- 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<class Class, class Registry>
- struct virtual_traits<std::unique_ptr<Class>, Registry> {
- //! `Class`, stripped from cv-qualifiers.
- using virtual_type = std::remove_cv_t<Class>;
- //! Return a reference to a non-modifiable `Class` object.
- //! @param arg A reference to a `std::unique_ptr<Class>`.
- //! @return A reference to the object pointed to.
- static auto peek(const std::unique_ptr<Class>& 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<Derived::element_type>`.
- template<typename Derived>
- static auto cast(std::unique_ptr<Class>&& ptr) {
- if constexpr (detail::requires_dynamic_cast<Class&, Derived&>) {
- auto p = &Registry::rtti::template dynamic_cast_ref<
- typename Derived::element_type&>(*ptr);
- ptr.release();
- return Derived(p);
- } else {
- auto p = &static_cast<typename Derived::element_type&>(*ptr);
- ptr.release();
- return Derived(p);
- }
- }
- //! Rebind to a different element type.
- //!
- //! @tparam Other The new element type.
- template<class Other>
- using rebind = std::unique_ptr<Other>;
- };
- //! Alias for a `virtual_ptr<std::unique_ptr<T>>`.
- template<class Class, class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
- using unique_virtual_ptr = virtual_ptr<std::unique_ptr<Class>, 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<Class, Registry>` 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<Registry>(
- std::make_unique<Class>(std::forward<T>(args)...));
- }
- namespace aliases {
- using boost::openmethod::make_unique_virtual;
- using boost::openmethod::unique_virtual_ptr;
- } // namespace aliases
- } // namespace boost::openmethod
- #endif
|