forked from boostorg/smart_ptr
Add generic pointer casts documentation
This commit is contained in:
@ -74,11 +74,10 @@ namespace boost {
|
|||||||
shared_ptr<T> allocate_shared(const A& a);
|
shared_ptr<T> allocate_shared(const A& a);
|
||||||
|
|
||||||
`// only if T is an array type of the form U[]`
|
`// only if T is an array type of the form U[]`
|
||||||
template<class T>
|
template<class T> shared_ptr<T>
|
||||||
shared_ptr<T> make_shared(std::size_t n, const remove_extent_t<T>& v);
|
make_shared(std::size_t n, const remove_extent_t<T>& v);
|
||||||
template<class T, class A>
|
template<class T, class A> shared_ptr<T>
|
||||||
shared_ptr<T>
|
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
||||||
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
|
||||||
|
|
||||||
`// only if T is an array type of the form U[N]`
|
`// only if T is an array type of the form U[N]`
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -226,14 +225,13 @@ Examples:::
|
|||||||
* `auto p = make_shared<double[6][2][2]>();`
|
* `auto p = make_shared<double[6][2][2]>();`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T>
|
template<class T> shared_ptr<T>
|
||||||
shared_ptr<T> make_shared(std::size_t n, const remove_extent_t<T>& v);
|
make_shared(std::size_t n, const remove_extent_t<T>& v);
|
||||||
```
|
```
|
||||||
::
|
::
|
||||||
```
|
```
|
||||||
template<class T, class A>
|
template<class T, class A> shared_ptr<T>
|
||||||
shared_ptr<T>
|
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
||||||
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
|
||||||
```
|
```
|
||||||
::
|
::
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
Remarks::: These overloads shall only participate in overload resolution when
|
||||||
|
@ -79,9 +79,8 @@ template<class T>
|
|||||||
std::unique_ptr<T> make_unique(remove_reference_t<T>&& v);
|
std::unique_ptr<T> make_unique(remove_reference_t<T>&& v);
|
||||||
```
|
```
|
||||||
::
|
::
|
||||||
Remarks:::
|
Remarks::: These overloads shall only participate in overload resolution when
|
||||||
* These overloads shall only participate in overload resolution when `T` is
|
`T` is not an array type.
|
||||||
not an array type.
|
|
||||||
Returns::: `std::unique_ptr<T>(new T(std::move(v))`.
|
Returns::: `std::unique_ptr<T>(new T(std::move(v))`.
|
||||||
Example::: `auto p = make_unique<std::vector<int> >({1, 2});`
|
Example::: `auto p = make_unique<std::vector<int> >({1, 2});`
|
||||||
|
|
||||||
|
@ -13,3 +13,201 @@ http://www.boost.org/LICENSE_1_0.txt
|
|||||||
:toc-title:
|
:toc-title:
|
||||||
:idprefix: pointer_cast_
|
:idprefix: pointer_cast_
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
The pointer cast function templates (`static_pointer_cast`,
|
||||||
|
`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`)
|
||||||
|
provide a way to write generic pointer castings for raw pointers,
|
||||||
|
`std::shared_ptr` and `std::unique_ptr`.
|
||||||
|
|
||||||
|
There is test and example code in
|
||||||
|
link:../../test/pointer_cast_test.cpp[pointer_cast_test.cpp]
|
||||||
|
|
||||||
|
## Rationale
|
||||||
|
|
||||||
|
Boost smart pointers usually overload those functions to provide a mechanism
|
||||||
|
to emulate pointers casts. For example, `shared_ptr<T>` implements a static
|
||||||
|
pointer cast this way:
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U>
|
||||||
|
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& p);
|
||||||
|
```
|
||||||
|
|
||||||
|
Pointer cast functions templates are overloads of `static_pointer_cast`,
|
||||||
|
`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`
|
||||||
|
for raw pointers, `std::shared_ptr` and `std::unique_ptr`. This way when
|
||||||
|
developing pointer type independent classes, for example, memory managers or
|
||||||
|
shared memory compatible classes, the same code can be used for raw and smart
|
||||||
|
pointers.
|
||||||
|
|
||||||
|
## Synopsis
|
||||||
|
|
||||||
|
The generic pointer casts are defined in `<boost/pointer_cast.hpp>`.
|
||||||
|
|
||||||
|
```
|
||||||
|
namespace boost {
|
||||||
|
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
|
||||||
|
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
|
||||||
|
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
|
||||||
|
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
|
||||||
|
|
||||||
|
template<class T, class U> std::shared_ptr<T>
|
||||||
|
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
|
template<class T, class U> std::shared_ptr<T>
|
||||||
|
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
|
template<class T, class U> std::shared_ptr<T>
|
||||||
|
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
|
template<class T, class U> std::shared_ptr<T>
|
||||||
|
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
|
|
||||||
|
template<class T, class U> std::unique_ptr<T>
|
||||||
|
static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
|
template<class T, class U> std::unique_ptr<T>
|
||||||
|
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
|
template<class T, class U> std::unique_ptr<T>
|
||||||
|
const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
|
template<class T, class U> std::unique_ptr<T>
|
||||||
|
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Free Functions
|
||||||
|
|
||||||
|
### static_pointer_cast
|
||||||
|
```
|
||||||
|
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Returns::: `static_cast<T*>(p)`
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> std::shared_ptr<T>
|
||||||
|
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Returns::: `std::static_pointer_cast<T>(p)`
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> std::unique_ptr<T>
|
||||||
|
static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Requires::: The expression `static_cast<T*>((U*)0)` must be well-formed.
|
||||||
|
Returns::: `std::unique_ptr<T>(static_cast<typename
|
||||||
|
std::unique_ptr<T>::element_type*>(p.release()))`.
|
||||||
|
|
||||||
|
CAUTION: The seemingly equivalent expression
|
||||||
|
`std::unique_ptr<T>(static_cast<T*>(p.get()))` will eventually result in
|
||||||
|
undefined behavior, attempting to delete the same object twice.
|
||||||
|
|
||||||
|
### dynamic_pointer_cast
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Returns::: `dynamic_cast<T*>(p)`
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> std::shared_ptr<T>
|
||||||
|
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Returns::: `std::dynamic_pointer_cast<T>(p)`
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> std::unique_ptr<T>
|
||||||
|
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Requires:::
|
||||||
|
* The expression `static_cast<T*>((U*)0)` must be well-formed.
|
||||||
|
* `T` must have a virtual destructor.
|
||||||
|
Returns:::
|
||||||
|
* When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())`
|
||||||
|
returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename
|
||||||
|
std::unique_ptr<T>::element_type*>(p.release()));`.
|
||||||
|
* Otherwise, `std::unique_ptr<T>()`.
|
||||||
|
|
||||||
|
### const_pointer_cast
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Returns::: `const_cast<T*>(p)`
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> std::shared_ptr<T>
|
||||||
|
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Returns::: `std::const_pointer_cast<T>(p)`
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> std::unique_ptr<T>
|
||||||
|
const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Requires::: The expression `const_cast<T*>((U*)0)` must be well-formed.
|
||||||
|
Returns::: `std::unique_ptr<T>(const_cast<typename
|
||||||
|
std::unique_ptr<T>::element_type*>(p.release()))`.
|
||||||
|
|
||||||
|
### reinterpret_pointer_cast
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Returns::: `reinterpret_cast<T*>(p)`
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> std::shared_ptr<T>
|
||||||
|
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Returns::: `std::reinterpret_pointer_cast<T>(p)`
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T, class U> std::unique_ptr<T>
|
||||||
|
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
|
```
|
||||||
|
::
|
||||||
|
Requires::: The expression `reinterpret_cast<T*>((U*)0)` must be well-formed.
|
||||||
|
Returns::: `std::unique_ptr<T>(reinterpret_cast<typename
|
||||||
|
std::unique_ptr<T>::element_type*>(p.release()))`.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
The following example demonstrates how the generic pointer casts help us
|
||||||
|
create pointer independent code.
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <boost/pointer_cast.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
class base {
|
||||||
|
public:
|
||||||
|
virtual ~base() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class derived : public base { };
|
||||||
|
|
||||||
|
template<class Ptr>
|
||||||
|
void check_if_it_is_derived(const Ptr& ptr)
|
||||||
|
{
|
||||||
|
assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
base* ptr = new derived;
|
||||||
|
boost::shared_ptr<base> sptr(new derived);
|
||||||
|
|
||||||
|
check_if_it_is_derived(ptr);
|
||||||
|
check_if_it_is_derived(sptr);
|
||||||
|
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
```
|
Reference in New Issue
Block a user