std_unique_ptr.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // Copyright (c) 2018-2025 Jean-Louis Leroy
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // See accompanying file LICENSE_1_0.txt
  4. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_OPENMETHOD_INTEROP_UNIQUE_PTR_HPP
  6. #define BOOST_OPENMETHOD_INTEROP_UNIQUE_PTR_HPP
  7. #include <boost/openmethod/core.hpp>
  8. #include <memory>
  9. namespace boost::openmethod {
  10. //! Specialize virtual_traits for std::unique_ptr by value.
  11. //!
  12. //! @tparam Class A class type, possibly cv-qualified.
  13. //! @tparam Registry A @ref registry.
  14. template<class Class, class Registry>
  15. struct virtual_traits<std::unique_ptr<Class>, Registry> {
  16. //! `Class`, stripped from cv-qualifiers.
  17. using virtual_type = std::remove_cv_t<Class>;
  18. //! Return a reference to a non-modifiable `Class` object.
  19. //! @param arg A reference to a `std::unique_ptr<Class>`.
  20. //! @return A reference to the object pointed to.
  21. static auto peek(const std::unique_ptr<Class>& arg) -> const Class& {
  22. return *arg;
  23. }
  24. //! Cast to a type.
  25. //!
  26. //! Cast a reference to the managed object, using `static_cast` if possible,
  27. //! and `Registry::rtti::dynamic_cast_ref` otherwise. If the cast succeeds,
  28. //! transfer ownership to a `std::unique_ptr` to the target type, and return
  29. //! it.
  30. //!
  31. //! @tparam Derived A xvalue reference to a `std::unique_ptr`.
  32. //! @param obj A xvalue reference to a `std::unique_ptr`.
  33. //! @return A `std::unique_ptr<Derived::element_type>`.
  34. template<typename Derived>
  35. static auto cast(std::unique_ptr<Class>&& ptr) {
  36. if constexpr (detail::requires_dynamic_cast<Class&, Derived&>) {
  37. auto p = &Registry::rtti::template dynamic_cast_ref<
  38. typename Derived::element_type&>(*ptr);
  39. ptr.release();
  40. return Derived(p);
  41. } else {
  42. auto p = &static_cast<typename Derived::element_type&>(*ptr);
  43. ptr.release();
  44. return Derived(p);
  45. }
  46. }
  47. //! Rebind to a different element type.
  48. //!
  49. //! @tparam Other The new element type.
  50. template<class Other>
  51. using rebind = std::unique_ptr<Other>;
  52. };
  53. //! Alias for a `virtual_ptr<std::unique_ptr<T>>`.
  54. template<class Class, class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
  55. using unique_virtual_ptr = virtual_ptr<std::unique_ptr<Class>, Registry>;
  56. //! Create a new object and return a `unique_virtual_ptr` to it.
  57. //!
  58. //! Create an object using `std::make_unique`, and return a @ref
  59. //! unique_virtual_ptr pointing to it. Since the exact class of the object is
  60. //! known, the `virtual_ptr` is created using @ref final_virtual_ptr.
  61. //!
  62. //! `Class` is _not_ required to be a polymorphic class.
  63. //!
  64. //! @tparam Class The class of the object to create.
  65. //! @tparam Registry A @ref registry.
  66. //! @tparam T Types of the arguments to pass to the constructor of `Class`.
  67. //! @param args Arguments to pass to the constructor of `Class`.
  68. //! @return A `unique_virtual_ptr<Class, Registry>` pointing to a newly
  69. //! created object of type `Class`.
  70. template<
  71. class Class, class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY,
  72. typename... T>
  73. inline auto make_unique_virtual(T&&... args) {
  74. return final_virtual_ptr<Registry>(
  75. std::make_unique<Class>(std::forward<T>(args)...));
  76. }
  77. namespace aliases {
  78. using boost::openmethod::make_unique_virtual;
  79. using boost::openmethod::unique_virtual_ptr;
  80. } // namespace aliases
  81. } // namespace boost::openmethod
  82. #endif