From 478a819cb5e63b4cf52fdfcebaa746e0079d9ea7 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 15 Jun 2017 01:36:59 -0400 Subject: [PATCH] Add generic pointer casts documentation --- doc/smart_ptr/make_shared.adoc | 18 ++- doc/smart_ptr/make_unique.adoc | 5 +- doc/smart_ptr/pointer_cast.adoc | 198 ++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 13 deletions(-) diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index 80afd39..3f69c72 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -74,11 +74,10 @@ namespace boost { shared_ptr allocate_shared(const A& a); `// only if T is an array type of the form U[]` - template - shared_ptr make_shared(std::size_t n, const remove_extent_t& v); - template - shared_ptr - allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); + template shared_ptr + make_shared(std::size_t n, const remove_extent_t& v); + template shared_ptr + allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); `// only if T is an array type of the form U[N]` template @@ -226,14 +225,13 @@ Examples::: * `auto p = make_shared();` ``` -template - shared_ptr make_shared(std::size_t n, const remove_extent_t& v); +template shared_ptr + make_shared(std::size_t n, const remove_extent_t& v); ``` :: ``` -template - shared_ptr - allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); +template shared_ptr + allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); ``` :: Remarks::: These overloads shall only participate in overload resolution when diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc index b01da5a..f3c413c 100644 --- a/doc/smart_ptr/make_unique.adoc +++ b/doc/smart_ptr/make_unique.adoc @@ -79,9 +79,8 @@ template std::unique_ptr make_unique(remove_reference_t&& v); ``` :: -Remarks::: -* These overloads shall only participate in overload resolution when `T` is -not an array type. +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type. Returns::: `std::unique_ptr(new T(std::move(v))`. Example::: `auto p = make_unique >({1, 2});` diff --git a/doc/smart_ptr/pointer_cast.adoc b/doc/smart_ptr/pointer_cast.adoc index cd65e4e..ccae283 100644 --- a/doc/smart_ptr/pointer_cast.adoc +++ b/doc/smart_ptr/pointer_cast.adoc @@ -13,3 +13,201 @@ http://www.boost.org/LICENSE_1_0.txt :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` implements a static +pointer cast this way: + +``` +template + shared_ptr static_pointer_cast(const shared_ptr& 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 ``. + +``` +namespace boost { + template T* static_pointer_cast(U* p) noexcept; + template T* dynamic_pointer_cast(U* p) noexcept; + template T* const_pointer_cast(U* p) noexcept; + template T* reinterpret_pointer_cast(U* p) noexcept; + + template std::shared_ptr + static_pointer_cast(const std::shared_ptr& p) noexcept; + template std::shared_ptr + dynamic_pointer_cast(const std::shared_ptr& p) noexcept; + template std::shared_ptr + const_pointer_cast(const std::shared_ptr& p) noexcept; + template std::shared_ptr + reinterpret_pointer_cast(const std::shared_ptr& p) noexcept; + + template std::unique_ptr + static_pointer_cast(std::unique_ptr&& p) noexcept; + template std::unique_ptr + dynamic_pointer_cast(std::unique_ptr&& p) noexcept; + template std::unique_ptr + const_pointer_cast(std::unique_ptr&& p) noexcept; + template std::unique_ptr + reinterpret_pointer_cast(std::unique_ptr&& p) noexcept; +} +``` + +## Free Functions + +### static_pointer_cast +``` +template T* static_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `static_cast(p)` + +``` +template std::shared_ptr + static_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::static_pointer_cast(p)` + +``` +template std::unique_ptr + static_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: The expression `static_cast((U*)0)` must be well-formed. +Returns::: `std::unique_ptr(static_cast::element_type*>(p.release()))`. + +CAUTION: The seemingly equivalent expression +`std::unique_ptr(static_cast(p.get()))` will eventually result in +undefined behavior, attempting to delete the same object twice. + +### dynamic_pointer_cast + +``` +template T* dynamic_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `dynamic_cast(p)` + +``` +template std::shared_ptr + dynamic_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::dynamic_pointer_cast(p)` + +``` +template std::unique_ptr + dynamic_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: +* The expression `static_cast((U*)0)` must be well-formed. +* `T` must have a virtual destructor. +Returns::: +* When `dynamic_cast::element_type*>(p.get())` +returns a non-zero value, `std::unique_ptr(dynamic_cast::element_type*>(p.release()));`. +* Otherwise, `std::unique_ptr()`. + +### const_pointer_cast + +``` +template T* const_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `const_cast(p)` + +``` +template std::shared_ptr + const_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::const_pointer_cast(p)` + +``` +template std::unique_ptr + const_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: The expression `const_cast((U*)0)` must be well-formed. +Returns::: `std::unique_ptr(const_cast::element_type*>(p.release()))`. + +### reinterpret_pointer_cast + +``` +template T* reinterpret_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `reinterpret_cast(p)` + +``` +template std::shared_ptr + reinterpret_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::reinterpret_pointer_cast(p)` + +``` +template std::unique_ptr + reinterpret_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: The expression `reinterpret_cast((U*)0)` must be well-formed. +Returns::: `std::unique_ptr(reinterpret_cast::element_type*>(p.release()))`. + +## Example + +The following example demonstrates how the generic pointer casts help us +create pointer independent code. + +``` +#include +#include + +class base { +public: + virtual ~base() { } +}; + +class derived : public base { }; + +template +void check_if_it_is_derived(const Ptr& ptr) +{ + assert(boost::dynamic_pointer_cast(ptr) != 0); +} + +int main() +{ + base* ptr = new derived; + boost::shared_ptr sptr(new derived); + + check_if_it_is_derived(ptr); + check_if_it_is_derived(sptr); + + delete ptr; +} +``` \ No newline at end of file