Update documentation.

This commit is contained in:
Peter Dimov
2016-09-10 20:57:35 +03:00
parent 94a04e57fb
commit 3aa720714d

View File

@ -2,16 +2,16 @@
<html> <html>
<head> <head>
<title>pointer_cast</title> <title>pointer_cast</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head> </head>
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
width="277" align="middle" border="0">pointer_cast</h1> width="277" align="middle" border="0" />pointer_cast</h1>
<p>The pointer cast functions (<code>boost::static_pointer_cast</code> <code>boost::dynamic_pointer_cast</code> <p>The pointer cast functions (<code>boost::static_pointer_cast</code> <code>boost::dynamic_pointer_cast</code>
<code>boost::reinterpret_pointer_cast</code> <code>boost::const_pointer_cast</code>) <code>boost::reinterpret_pointer_cast</code> <code>boost::const_pointer_cast</code>)
provide a way to write generic pointer castings for raw pointers, std::shared_ptr and std::unique_ptr. The functions provide a way to write generic pointer castings for raw pointers, <code>std::shared_ptr</code> and <code>std::unique_ptr</code>. The functions
are defined in <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A>.</CITE></p> are defined in <cite><a href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</a>.</cite></p>
<P>There is test/example code in <CITE><A href="test/pointer_cast_test.cpp">pointer_cast_test.cpp</A></CITE>.</p> <p>There is test/example code in <cite><a href="test/pointer_cast_test.cpp">pointer_cast_test.cpp</a></cite>.</p>
<h2><a name="rationale">Rationale</a></h2> <h2><a name="rationale">Rationale</a></h2>
<P>Boost smart pointers usually overload those functions to provide a mechanism to <P>Boost smart pointers usually overload those functions to provide a mechanism to
emulate pointers casts. For example, <code>boost::shared_ptr&lt;...&gt;</code> implements emulate pointers casts. For example, <code>boost::shared_ptr&lt;...&gt;</code> implements
@ -20,15 +20,15 @@
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; static_pointer_cast(shared_ptr&lt;U&gt; const &amp;r); shared_ptr&lt;T&gt; static_pointer_cast(shared_ptr&lt;U&gt; const &amp;r);
</pre> </pre>
<P>Pointer cast functions from <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A></CITE> <p>Pointer cast functions from <cite><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A></CITE>
are overloads of <code>boost::static_pointer_cast</code>, <code>boost::dynamic_pointer_cast</code>, are overloads of <code>boost::static_pointer_cast</code>, <code>boost::dynamic_pointer_cast</code>,
<code>boost::reinterpret_pointer_cast</code> and <code>boost::const_pointer_cast</code> <code>boost::reinterpret_pointer_cast</code> and <code>boost::const_pointer_cast</code>
for raw pointers, std::shared_ptr and std::unique_ptr. This way when developing pointer type independent classes, for raw pointers, <code>std::shared_ptr</code> and <code>std::unique_ptr</code>. This way when developing
for example, memory managers or shared memory compatible classes, the same code pointer type independent classes, for example, memory managers or shared memory compatible classes, the same
can be used for raw and smart pointers.</p> code can be used for raw and smart pointers.</p>
<H2><A name="synopsis">Synopsis</A></H2> <h2><a name="synopsis">Synopsis</a></h2>
<BLOCKQUOTE> <blockquote>
<PRE> <pre>
namespace boost { namespace boost {
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
@ -48,84 +48,91 @@ inline T* reinterpret_pointer_cast(U *ptr)
{ return reinterpret_cast&lt;T*&gt;(ptr); } { return reinterpret_cast&lt;T*&gt;(ptr); }
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
inline std::shared_ptr&lt;U&gt; static_pointer_cast(std::shared_ptr&lt;T&gt; ptr); inline std::shared_ptr&lt;T&gt; static_pointer_cast(std::shared_ptr&lt;U&gt; const&amp; r);
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
inline std::shared_ptr&lt;U&gt; dynamic_pointer_cast(std::shared_ptr&lt;T&gt; ptr); inline std::shared_ptr&lt;T&gt; dynamic_pointer_cast(std::shared_ptr&lt;U&gt; const&amp; r);
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
inline std::shared_ptr&lt;U&gt; const_pointer_cast(std::shared_ptr&lt;T&gt; ptr); inline std::shared_ptr&lt;T&gt; const_pointer_cast(std::shared_ptr&lt;U&gt; const&amp; r);
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
inline std::shared_ptr&lt;U&gt; reinterpret_pointer_cast(std::shared_ptr&lt;T&gt; ptr); inline std::shared_ptr&lt;T&gt; reinterpret_pointer_cast(std::shared_ptr&lt;U&gt; const&amp; r);
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
inline std::unique_ptr&lt;U&gt; static_pointer_cast(std::unique_ptr&lt;T&gt; &amp;&amp;ptr); inline std::unique_ptr&lt;T&gt; static_pointer_cast(std::unique_ptr&lt;U&gt;&amp;&amp; r);
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
inline std::unique_ptr&lt;U&gt; dynamic_pointer_cast(std::unique_ptr&lt;T&gt; &amp;&amp;ptr); inline std::unique_ptr&lt;T&gt; dynamic_pointer_cast(std::unique_ptr&lt;U&gt;&amp;&amp; r);
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
inline std::unique_ptr&lt;U&gt; const_pointer_cast(std::unique_ptr&lt;T&gt; &amp;&amp;ptr); inline std::unique_ptr&lt;T&gt; const_pointer_cast(std::unique_ptr&lt;U&gt;&amp;&amp; r);
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
inline std::unique_ptr&lt;U&gt; reinterpret_pointer_cast(std::unique_ptr&lt;T&gt; &amp;&amp;ptr); inline std::unique_ptr&lt;T&gt; reinterpret_pointer_cast(std::unique_ptr&lt;U&gt;&amp;&amp; r);
} // namespace boost } // namespace boost
</PRE> </pre>
</BLOCKQUOTE> </blockquote>
<P>As you can see from the above synopsis, the pointer cast functions for raw pointers are just <p>As you can see from the above synopsis, the pointer cast functions for raw pointers are just
wrappers around standard C++ cast operators.</P> wrappers around standard C++ cast operators.</p>
<H2><A name="memory_safety">Memory Safety</A></H2> <p>The pointer casts for <code>std::shared_ptr</code> are aliases of the corresponding standard
<P>It is possible to write unsafe code, when upcasting to a base type without virtual destructor. functions with the same names and equivalent to <a href="shared_ptr.htm#static_pointer_cast">the
Consider the following example:</P> functions taking <code>boost::shared_ptr</code></a>.</p>
<PRE>
#include &lt;memory&gt;
#include &lt;utility&gt;
#include &lt;boost/pointer_cast.hpp&gt;
#include &lt;boost/make_unique.hpp&gt;
int destructed = 0; <p>The pointer casts for <code>std::unique_ptr</code> are documented below.</p>
struct base { <h3 id="static_pointer_cast">static_pointer_cast</h3>
~base() { <pre>template&lt;class T, class U&gt;
// ... unique_ptr&lt;T&gt; static_pointer_cast(unique_ptr&lt;U&gt;&amp;&amp; r); // never throws</pre>
} <blockquote>
}; <p><b>Requires:</b> The expression <code>static_cast&lt;T*&gt;( (U*)0 )</code>
must be well-formed.</p>
<p><b>Returns:</b> <code>unique_ptr&lt;T&gt;( static_cast&lt;typename unique_ptr&lt;T&gt;::element_type*&gt;(r.release()) )</code>.</p>
<p><b>Throws:</b> nothing.</p>
<p><b>Notes:</b> the seemingly equivalent expression
<code>unique_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code>
will eventually result in undefined behavior, attempting to delete the same
object twice.</p>
</blockquote>
<h3 id="const_pointer_cast">const_pointer_cast</h3>
<pre>template&lt;class T, class U&gt;
unique_ptr&lt;T&gt; const_pointer_cast(unique_ptr&lt;U&gt;&amp;&amp; r); // never throws</pre>
<blockquote>
<p><b>Requires:</b> The expression <code>const_cast&lt;T*&gt;( (U*)0 )</code>
must be well-formed.</p>
<p><b>Returns:</b> <code>unique_ptr&lt;T&gt;( const_cast&lt;typename unique_ptr&lt;T&gt;::element_type*&gt;(r.release()) )</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3 id="dynamic_pointer_cast">dynamic_pointer_cast</h3>
<pre>template&lt;class T, class U&gt;
unique_ptr&lt;T&gt; dynamic_pointer_cast(unique_ptr&lt;U&gt;&amp;&amp; r);</pre>
<blockquote>
<p><b>Requires:</b> The expression <code>dynamic_cast&lt;T*&gt;( (U*)0 )</code>
must be well-formed. <code>T</code> must have a virtual destructor.</p>
<p><b>Returns:</b></p>
<ul>
<li>
When <code>dynamic_cast&lt;typename unique_ptr&lt;T&gt;::element_type*&gt;(r.get())</code> returns a nonzero value,
<code>unique_ptr&lt;T&gt;(dynamic_cast&lt;typename unique_ptr&lt;T&gt;::element_type*&gt;(r.release()))</code>;</li>
<li>
Otherwise, <code>unique_ptr&lt;T&gt;()</code>.</li></ul>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3 id="reinterpret_pointer_cast">reinterpret_pointer_cast</h3>
<pre>template&lt;class T, class U&gt;
unique_ptr&lt;T&gt; reinterpret_pointer_cast(unique_ptr&lt;U&gt;&amp;&amp; r); // never throws</pre>
<blockquote>
<p><b>Requires:</b> The expression <code>reinterpret_cast&lt;T*&gt;( (U*)0 )</code>
must be well-formed.</p>
<p><b>Returns:</b> <code>unique_ptr&lt;T&gt;( reinterpret_cast&lt;typename unique_ptr&lt;T&gt;::element_type*&gt;(r.release()) )</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
struct child : base { <h2><a name="example">Example</a></h2>
virtual ~child() { <blockquote>
destructed++; <pre>
}
}
int main() {
{
std::unique_ptr<child> tmp = boost::make_unique<child>();
std::unique_ptr<base> sink = boost::static_pointer_cast<base>( std::move(tmp) );
}
// child::~child was never called
assert(destructed == 0);
return 0;
}
</PRE>
<P>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.</P>
<P>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.</P>
<P>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.</P>
<P>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.</P>
<H2><A name="example">Example</A></H2>
<BLOCKQUOTE>
<PRE>
#include &lt;boost/pointer_cast.hpp&gt; #include &lt;boost/pointer_cast.hpp&gt;
#include &lt;boost/shared_ptr.hpp&gt; #include &lt;boost/shared_ptr.hpp&gt;
@ -150,28 +157,27 @@ void check_if_it_is_derived(const BasePtr &amp;ptr)
int main() int main()
{ {
<I>// Create a raw and a shared_ptr</I> <em>// Create a raw and a shared_ptr</em>
base *ptr = new derived; base *ptr = new derived;
boost::shared_ptr&lt;base&gt; sptr(new derived); boost::shared_ptr&lt;base&gt; sptr(new derived);
<I>// Check that base pointer points actually to derived class</I> <em>// Check that base pointer points actually to derived class</em>
check_if_it_is_derived(ptr); check_if_it_is_derived(ptr);
check_if_it_is_derived(sptr); check_if_it_is_derived(sptr);
// <EM>Ok!</EM> <em>// Ok!</em>
delete ptr; delete ptr;
return 0; return 0;
}</PRE> }</pre>
</BLOCKQUOTE> </blockquote>
<P>The example demonstrates how the generic pointer casts help us create pointer <p>The example demonstrates how the generic pointer casts help us create pointer
independent code.</P> independent code.</p>
<hr> <hr />
<p>$Date$</p>
<p>Copyright 2005 Ion Gazta<74>aga. Use, modification, and distribution are subject to <p>Copyright 2005 Ion Gazta<74>aga. Use, modification, and distribution are subject to
the Boost Software License, Version 1.0. (See accompanying file <A href="../../LICENSE_1_0.txt"> the Boost Software License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">
LICENSE_1_0.txt</A> or a copy at &lt;<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>&gt;.)</p> LICENSE_1_0.txt</a> or a copy at &lt;<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>&gt;.)</p>
</body> </body>
</html> </html>