Files
openmethod/doc/virtual_ptr.adoc
2025-09-28 16:08:11 -04:00

334 lines
9.3 KiB
Plaintext

[#virtual_ptr]
:idprefix: virtual_ptr_
## virtual_ptr
### Synopsis
`virtual_ptr` is defined in `<boost/openmethod/core.hpp>`.
```c++
namespace boost::openmethod {
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
class virtual_ptr {
public:
static constexpr bool is_smart_ptr = /* see below */;
using element_type = /* see below */;
virtual_ptr();
virtual_ptr(nullptr_t);
template<class Other> virtual_ptr(Other& other);
template<class Other> virtual_ptr(const Other& other);
template<class Other> virtual_ptr(Other&& other);
virtual_ptr& operator =(nullptr_t);
template<class Other> virtual_ptr& operator =(Other& other);
template<class Other> virtual_ptr& operator =(const Other& other);
template<class Other> virtual_ptr& operator =(Other&& other);
template<class Other>
static auto final(Other&& obj);
auto get() const -> element_type*;
auto operator->() const -> element_type*;
auto operator*() const -> element_type&;
auto pointer() const -> const Class*&;
template<typename Other>
auto cast() const -> virtual_ptr<Other, Policy>;
};
template<class Class>
virtual_ptr(Class&) -> virtual_ptr<Class, BOOST_OPENMETHOD_DEFAULT_REGISTRY>;
template<class Class>
inline auto final_virtual_ptr(Class& obj) -> virtual_ptr<
Class, BOOST_OPENMETHOD_DEFAULT_REGISTRY>;
template<class Policy, class Class>
inline auto final_virtual_ptr(Class& obj) -> virtual_ptr<Class, Policy>;
template<class Left, class Right, class Policy>
auto operator==(
const virtual_ptr<Left, Policy>& left,
const virtual_ptr<Right, Policy>& right) -> bool;
template<class Left, class Right, class Policy>
auto operator!=(
const virtual_ptr<Left, Policy>& left,
const virtual_ptr<Right, Policy>& right) -> bool;
} // namespace boost::openmethod
```
Defined in `<boost/openmethod/interop/std_shared_ptr.hpp>`:
```c++
namespace boost::openmethod {
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
using shared_virtual_ptr = virtual_ptr<std::shared_ptr<Class>, Policy>;
template<
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T>
inline auto make_shared_virtual(T&&... args)
-> shared_virtual_ptr<Class, Policy>;
}
```
Defined in `<boost/openmethod/interop/std_unique_ptr.hpp>`:
```c++
namespace boost::openmethod {
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
using unique_virtual_ptr = virtual_ptr<std::unique_ptr<Class>, Policy>;
template<
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T>
inline auto make_unique_virtual(T&&... args)
-> unique_virtual_ptr<Class, Policy>;
}
```
### Description
`virtual_ptr` is a wide pointer that combines a pointer to an object and a
pointer to its v-table. The object pointer can be a plain pointer or a smart
pointer. Specializations of `virtual_traits` are required for smart pointers.
They are provided for `std::unique_ptr` and `std::shared_ptr`.
A plain `virtual_ptr` can be constructed from a reference, a smart pointer, or
another `virtual_ptr`. A smart `virtual_ptr` can be constructed from a smart
pointer or from a smart `virtual_ptr`. Usual conversions - from derived to base,
and from non-const to const - are supported.
### Members
#### is_smart_ptr
```c++
static constexpr bool is_smart_ptr;
```
`true` if `Class` is a smart pointer, `false` otherwise. The value is derived
from `virtual_traits<Class, Policy>`: if it has a member template called
`rebind`, `Class` is considered a smart pointer.
#### element_type
```c++
using element_type = std::conditional_t<
is_smart_ptr, typename Class::element_type, Class>;
```
The class of the object pointed to.
#### constructors
[source,c++]
----
virtual_ptr(); // 1
virtual_ptr(nullptr_t); // 2
template<class Other> virtual_ptr(Other& other); // 3
template<class Other> virtual_ptr(const Other& other); // 4
template<class Other> virtual_ptr(Other&& other); // 5
template<class Other> virtual_ptr(Other* other); // 6
----
(1) Default constructor. Sets the v-table pointer to `nullptr`. If `Class` is
_not_ a smart pointer, the value of object pointer is is undefined.
(2) Sets both the object and v-table pointers to `nullptr`.
(3), (4) For plain `virtual_ptr`{empty}s, `other` must be either a lvalue
reference to an object of a registered class, or a `virtual_ptr` (plain or
smart). For smart `virtual_ptr`{empty}s, `other` must be a reference to a smart
pointer, or a reference to a smart `virtual_ptr`.
(5) Constructs a `virtual_ptr` from a smart pointer or a smart `virtual_ptr`.
The object pointer is moved from `other`.
(6) Constructs a `virtual_ptr` from a plain pointer. Available only for plain
`virtual_ptr`{empty}s.
If `other` is also a `virtual_ptr`, the v-table pointer is copied from it.
Otherwise, it is deduced from the object. The `Policy` must be the same for both
`virtual_ptr`{empty}s.
#### assignment operators
[source,c++]
----
virtual_ptr& operator =(nullptr_t); // 1
template<class Other> virtual_ptr& operator =(Other& other); // 2
template<class Other> virtual_ptr& operator =(const Other& other); // 3
template<class Other> virtual_ptr& operator =(Other&& other); // 4
template<class Other> virtual_ptr& operator =(Other* other); // 5
----
(1) Sets both the object and v-table pointers to `nullptr`.
(2), (3) For plain `virtual_ptr`{empty}s, `other` must be either a lvalue
reference to an object of a registered class, or a `virtual_ptr` (plain or
smart). For smart `virtual_ptr`{empty}s, `other` must be a reference to a smart
pointer, or a reference to a smart `virtual_ptr`.
(4) Moves `other` to this `virtual_ptr`. If `other` is a smart pointer or a
smart virtual pointer, the object pointer is moved from `other`.
(5) Sets the object pointer to `other`. Available only for plain
`virtual_ptr`{empty}s.
If `other` is also a `virtual_ptr`, the v-table pointer is copied from it.
Otherwise, it is deduced from the object. The `Policy` must be the same for both
`virtual_ptr`{empty}s.
#### final
```c++
template<class Other>
static auto final(Other&& obj);
```
Constructs a `virtual_ptr` from a reference to an object, or from a smart
pointer. It is assumed that the static and dynamic types are the same. The
v-table pointer is initialized from the `Policy::static_vptr` for the class,
which needs not be polymorphic.
#### get
```c++
auto get() const -> element_type*;
```
Returns a pointer to the object.
#### operator->
```c++
auto operator->() const -> element_type*;
```
Returns a pointer to the object.
#### operator*
```c++
auto operator*() const -> element_type&;
```
Returns a reference to the object.
#### pointer
```c++
auto pointer() const;
```
Returns a reference to the object pointer, which can be either a plain pointer
or a smart pointer.
#### cast
```c++
template<typename Other>
auto cast() const -> virtual_ptr<Other, Policy>;
```
Returns a `virtual_ptr` to the same object, cast to `Other`.
### Deduction guide
```c++
template<class Class>
virtual_ptr(Class&) -> virtual_ptr<Class, BOOST_OPENMETHOD_DEFAULT_REGISTRY>;
```
---
### Non-members
#### virtual_shared_ptr
```c++
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
using virtual_shared_ptr = virtual_ptr<std::shared_ptr<Class>, Policy>;
```
Convenience alias for `virtual_ptr<std::shared_ptr<Class>, Policy>`.
#### virtual_unique_ptr
```c++
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
using virtual_unique_ptr = virtual_ptr<std::unique_ptr<Class>, Policy>;
```
Convenience alias for `virtual_ptr<std::unique_ptr<Class>, Policy>`.
#### final_virtual_ptr
```c++
template<class Policy, class Class>
inline auto final_virtual_ptr(Class&& obj);
template<class Class>
inline auto final_virtual_ptr(Class&& obj);
```
Utility functions, forwarding to `virtual_ptr<Class, Policy>::final`.
If `Policy` is not specified, `BOOST_OPENMETHOD_DEFAULT_REGISTRY` is used.
#### make_shared_virtual
```c++
template<
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T>
inline auto make_shared_virtual(T&&... args)
-> shared_virtual_ptr<Class, Policy>;
```
Creates an object using `std::make_shared` and returns a `virtual_shared_ptr` to
it. The v-table pointer is initialized from the the `Policy::static_vptr` for
the class, which needs not be polymorphic.
#### make_unique_virtual
```c++
template<
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T>
inline auto make_unique_virtual(T&&... args)
-> unique_virtual_ptr<Class, Policy>;
```
Creates an object using `std::make_unique` and returns a `virtual_unique_ptr` to
it. The v-table pointer is initialized from the the `Policy::static_vptr` for
the class, which needs not be polymorphic.
#### operator==
```c++
template<class Left, class Right, class Policy>
auto operator==(
const virtual_ptr<Left, Policy>& left,
const virtual_ptr<Right, Policy>& right) -> bool;
```
Compares two `virtual_ptr` objects for equality.
#### operator!=
```c++
template<class Left, class Right, class Policy>
auto operator!=(
const virtual_ptr<Left, Policy>& left,
const virtual_ptr<Right, Policy>& right) -> bool;
```
Compares two `virtual_ptr` objects for inequality.