From 3aa720714d76b57fd758e2507bd0c0d1105e60b4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 10 Sep 2016 20:57:35 +0300 Subject: [PATCH] Update documentation. --- pointer_cast.html | 168 ++++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 81 deletions(-) diff --git a/pointer_cast.html b/pointer_cast.html index f0c7fa2..bf63043 100644 --- a/pointer_cast.html +++ b/pointer_cast.html @@ -2,16 +2,16 @@ pointer_cast - +

boost.png (6897 bytes)pointer_cast

+ width="277" align="middle" border="0" />pointer_cast

The pointer cast functions (boost::static_pointer_cast boost::dynamic_pointer_cast boost::reinterpret_pointer_cast boost::const_pointer_cast) - provide a way to write generic pointer castings for raw pointers, std::shared_ptr and std::unique_ptr. The functions - are defined in boost/pointer_cast.hpp.

-

There is test/example code in pointer_cast_test.cpp.

+ provide a way to write generic pointer castings for raw pointers, std::shared_ptr and std::unique_ptr. The functions + are defined in boost/pointer_cast.hpp.

+

There is test/example code in pointer_cast_test.cpp.

Rationale

Boost smart pointers usually overload those functions to provide a mechanism to emulate pointers casts. For example, boost::shared_ptr<...> implements @@ -20,15 +20,15 @@ template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const &r); -

Pointer cast functions from boost/pointer_cast.hpp +

Pointer cast functions from boost/pointer_cast.hpp are overloads of boost::static_pointer_cast, boost::dynamic_pointer_cast, boost::reinterpret_pointer_cast and boost::const_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

-
-
+            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

+
+
 namespace boost {
 
 template<class T, class U>
@@ -48,84 +48,91 @@ inline T* reinterpret_pointer_cast(U *ptr)
   { return reinterpret_cast<T*>(ptr); }
 
 template<class T, class U>
-inline std::shared_ptr<U> static_pointer_cast(std::shared_ptr<T> ptr);
+inline std::shared_ptr<T> static_pointer_cast(std::shared_ptr<U> const& r);
 
 template<class T, class U>
-inline std::shared_ptr<U> dynamic_pointer_cast(std::shared_ptr<T> ptr);
+inline std::shared_ptr<T> dynamic_pointer_cast(std::shared_ptr<U> const& r);
 
 template<class T, class U>
-inline std::shared_ptr<U> const_pointer_cast(std::shared_ptr<T> ptr);
+inline std::shared_ptr<T> const_pointer_cast(std::shared_ptr<U> const& r);
 
 template<class T, class U>
-inline std::shared_ptr<U> reinterpret_pointer_cast(std::shared_ptr<T> ptr);
+inline std::shared_ptr<T> reinterpret_pointer_cast(std::shared_ptr<U> const& r);
 
 template<class T, class U>
-inline std::unique_ptr<U> static_pointer_cast(std::unique_ptr<T> &&ptr);
+inline std::unique_ptr<T> static_pointer_cast(std::unique_ptr<U>&& r);
 
 template<class T, class U>
-inline std::unique_ptr<U> dynamic_pointer_cast(std::unique_ptr<T> &&ptr);
+inline std::unique_ptr<T> dynamic_pointer_cast(std::unique_ptr<U>&& r);
 
 template<class T, class U>
-inline std::unique_ptr<U> const_pointer_cast(std::unique_ptr<T> &&ptr);
+inline std::unique_ptr<T> const_pointer_cast(std::unique_ptr<U>&& r);
 
 template<class T, class U>
-inline std::unique_ptr<U> reinterpret_pointer_cast(std::unique_ptr<T> &&ptr);
+inline std::unique_ptr<T> reinterpret_pointer_cast(std::unique_ptr<U>&& r);
   
 } // namespace boost
-
-
-

As you can see from the above synopsis, the pointer cast functions for raw pointers are just - wrappers around standard C++ cast operators.

+
+
+

As you can see from the above synopsis, the pointer cast functions for raw pointers are just + wrappers around standard C++ cast operators.

-

Memory Safety

-

It is possible to write unsafe code, when upcasting to a base type without virtual destructor. - Consider the following example:

-
-#include <memory>
-#include <utility>
-#include <boost/pointer_cast.hpp>
-#include <boost/make_unique.hpp>
+        

The pointer casts for std::shared_ptr are aliases of the corresponding standard + functions with the same names and equivalent to the + functions taking boost::shared_ptr.

-int destructed = 0; +

The pointer casts for std::unique_ptr are documented below.

-struct base { - ~base() { - // ... - } -}; +

static_pointer_cast

+
template<class T, class U>
+  unique_ptr<T> static_pointer_cast(unique_ptr<U>&& r); // never throws
+
+

Requires: The expression static_cast<T*>( (U*)0 ) + must be well-formed.

+

Returns: unique_ptr<T>( static_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

+

Throws: nothing.

+

Notes: the seemingly equivalent expression + unique_ptr<T>(static_cast<T*>(r.get())) + will eventually result in undefined behavior, attempting to delete the same + object twice.

+
+

const_pointer_cast

+
template<class T, class U>
+  unique_ptr<T> const_pointer_cast(unique_ptr<U>&& r); // never throws
+
+

Requires: The expression const_cast<T*>( (U*)0 ) + must be well-formed.

+

Returns: unique_ptr<T>( const_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

+

Throws: nothing.

+
+

dynamic_pointer_cast

+
template<class T, class U>
+  unique_ptr<T> dynamic_pointer_cast(unique_ptr<U>&& r);
+
+

Requires: The expression dynamic_cast<T*>( (U*)0 ) + must be well-formed. T must have a virtual destructor.

+

Returns:

+
    +
  • + When dynamic_cast<typename unique_ptr<T>::element_type*>(r.get()) returns a nonzero value, + unique_ptr<T>(dynamic_cast<typename unique_ptr<T>::element_type*>(r.release()));
  • +
  • + Otherwise, unique_ptr<T>().
+

Throws: nothing.

+
+

reinterpret_pointer_cast

+
template<class T, class U>
+  unique_ptr<T> reinterpret_pointer_cast(unique_ptr<U>&& r); // never throws
+
+

Requires: The expression reinterpret_cast<T*>( (U*)0 ) + must be well-formed.

+

Returns: unique_ptr<T>( reinterpret_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

+

Throws: nothing.

+
-struct child : base { - virtual ~child() { - destructed++; - } -} - -int main() { - { - std::unique_ptr tmp = boost::make_unique(); - std::unique_ptr sink = boost::static_pointer_cast( std::move(tmp) ); - } - - // child::~child was never called - assert(destructed == 0); - - return 0; -} -
-

In this example, the child destructor child::~child was never called, because the child* in tmp - was downcast to a base* and moved into sink. The destructor of tmp did essentially nothing, because - it contained nullptr during destruction; sink deleted the pointer, but since base::~base is non-virtual - the child destructor was never called.

-

boost::static_pointer_cast and boost::dynamic_pointer_cast for std::unique_ptr prevent the above scenario - by raising a compiler error when such a cast is detected.

-

The overloads for std::shared_ptr and boost::shared_ptr are not prone to this problem, since they internally - always store the original pointer with the original type.

-

The plain pointer casts are in principle also prone to that problem, but it is assumed that raw pointers - are non-owning, so no checking is performed.

- -

Example

-
-
+        

Example

+
+
 #include <boost/pointer_cast.hpp>
 #include <boost/shared_ptr.hpp>
 
@@ -150,28 +157,27 @@ void check_if_it_is_derived(const BasePtr &ptr)
 
 int main()
 {
-   // Create a raw and a shared_ptr
+   // Create a raw and a shared_ptr
 
    base *ptr = new derived;
    boost::shared_ptr<base> sptr(new derived);
    
-   // Check that base pointer points actually to derived class
+   // Check that base pointer points actually to derived class
 
    check_if_it_is_derived(ptr);
    check_if_it_is_derived(sptr);
    
-   // Ok!
+   // Ok!
    
    delete ptr;
    return 0;
-}
-
-

The example demonstrates how the generic pointer casts help us create pointer - independent code.

-
-

$Date$

+}
+
+

The example demonstrates how the generic pointer casts help us create pointer + independent code.

+

Copyright 2005 Ion Gaztaņaga. Use, modification, and distribution are subject to - the Boost Software License, Version 1.0. (See accompanying file - LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

+ the Boost Software License, Version 1.0. (See accompanying file + LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)