blob: 5c2ef54c32fd020bf714b324a2ed02ab707b63ca [file] [log] [blame]
////
Copyright 2017 Peter Dimov
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
////
[#pointer_cast]
# Generic Pointer Casts
:toc:
:toc-title:
: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;
```
[none]
* {blank}
+
Returns:: `static_cast<T*>(p)`
```
template<class T, class U> std::shared_ptr<T>
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
```
[none]
* {blank}
+
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;
```
[none]
* {blank}
+
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;
```
[none]
* {blank}
+
Returns:: `dynamic_cast<T*>(p)`
```
template<class T, class U> std::shared_ptr<T>
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
```
[none]
* {blank}
+
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;
```
[none]
* {blank}
+
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;
```
[none]
* {blank}
+
Returns:: `const_cast<T*>(p)`
```
template<class T, class U> std::shared_ptr<T>
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
```
[none]
* {blank}
+
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;
```
[none]
* {blank}
+
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;
```
[none]
* {blank}
+
Returns:: `reinterpret_cast<T*>(p)`
```
template<class T, class U> std::shared_ptr<T>
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
```
[none]
* {blank}
+
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;
```
[none]
* {blank}
+
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;
}
```