forked from boostorg/conversion
Add polymorphic_pointer_cast
This commit is contained in:
28
cast.htm
28
cast.htm
@ -30,7 +30,8 @@
|
||||
<code><a href="#Polymorphic_cast">polymorphic_cast</a></code> and
|
||||
<code><a href="#Polymorphic_cast">polymorphic_downcast</a></code>
|
||||
function templates designed to complement the C++ built-in casts.</p> <p>The header <a href="../../boost/polymorphic_pointer_cast.hpp">boost/polymorphic_pointer_cast.hpp</a> provides
|
||||
<code><a href="#Polymorphic_cast">polymorphic_pointer_downcast</a></code> function template.
|
||||
<code><a href="#Polymorphic_cast">polymorphic_pointer_cast</a></code> and
|
||||
<code><a href="#Polymorphic_cast">polymorphic_pointer_downcast</a></code> function templates.
|
||||
|
||||
<p>The program <a href="test/cast_test.cpp">cast_test.cpp</a> can be used to
|
||||
verify these function templates work as expected.</p>
|
||||
@ -79,7 +80,7 @@
|
||||
<b>Warning:</b> Because <code>polymorphic_downcast</code> uses assert(), it
|
||||
violates the One Definition Rule (ODR) if NDEBUG is inconsistently
|
||||
defined across translation units. [See ISO Std 3.2]
|
||||
</p><p>
|
||||
<p>
|
||||
For crosscasts, or when the success of a cast can only be known at
|
||||
runtime, or when efficiency is not important,
|
||||
<code>polymorphic_cast</code> is preferred. </p>
|
||||
@ -89,13 +90,18 @@
|
||||
whether a given interface is supported; in that case a return of 0 isn't
|
||||
an error condition.</p>
|
||||
|
||||
<p>While <code>polymorphic_downcast</code> works with built-in pointer types only,
|
||||
<code>polymorphic_pointer_downcast</code> is a more generic version
|
||||
<p>While <code>polymorphic_downcast</code> and <code>polymorphic_cast</code> work with built-in pointer types only,
|
||||
<code>polymorphic_pointer_downcast</code> and <code>polymorphic_pointer_cast</code> are more generic versions
|
||||
with support for any pointer type for which the following expressions would be valid:<br><br>
|
||||
<code> static_pointer_cast<Derived>(p);<br> dynamic_pointer_cast<Derived>(p);</code><br><br>
|
||||
This includes C++ built-in pointers, <code>std::shared_ptr, boost::shared_ptr, boost::intrusive_ptr</code>, etc.</p>
|
||||
|
||||
<h3>polymorphic_cast, polymorphic_downcast and polymorphic_pointer_downcast synopsis</h3>
|
||||
<p> For <code>polymorphic_pointer_downcast</code>:</p>
|
||||
<code> static_pointer_cast<Derived>(p);<br> dynamic_pointer_cast<Derived>(p);</code><br><br>
|
||||
|
||||
<p> For <code>polymorphic_pointer_cast</code>:</p>
|
||||
<code> dynamic_pointer_cast<Derived>(p);<br> !p; // conversion to bool with negation</code><br><br>
|
||||
<p>This includes C++ built-in pointers, <code>std::shared_ptr, boost::shared_ptr, boost::intrusive_ptr</code>, etc.</p>
|
||||
|
||||
<h3>polymorphic_cast, polymorphic_downcast, polymorphic_pointer_cast and polymorphic_pointer_downcast synopsis</h3>
|
||||
|
||||
<blockquote>
|
||||
<pre>namespace boost {
|
||||
@ -110,6 +116,11 @@ inline Derived polymorphic_downcast(Base* x);
|
||||
// Effects: assert( dynamic_cast<Derived>(x) == x );
|
||||
// Returns: static_cast<Derived>(x)
|
||||
|
||||
template <class Derived, class Base>
|
||||
inline Derived polymorphic_pointer_cast(Base* x);
|
||||
// Throws: std::bad_cast if ( dynamic_pointer_cast<Derived>(x) == 0 )
|
||||
// Returns: dynamic_pointer_cast<Derived>(x)
|
||||
|
||||
template <class Derived, class Base>
|
||||
inline auto polymorphic_pointer_downcast(Base x);
|
||||
// Effects: assert( dynamic_pointer_cast<Derived>(x) == x );
|
||||
@ -165,7 +176,8 @@ void f(FruitPtr fruit)
|
||||
<code>polymorphic_downcast</code> was contributed by <a href=
|
||||
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>.<br>
|
||||
<code>polymorphic_pointer_downcast</code> was contributed by <a href=
|
||||
"http://www.boost.org/people/boris_rasin.htm">Boris Rasin</a>.<br>
|
||||
"http://www.boost.org/people/boris_rasin.htm">Boris Rasin</a> and
|
||||
<code>polymorphic_pointer_cast</code> by Antony Polukhin.<br>
|
||||
An old
|
||||
<code>numeric_cast</code> that was contributed by <a href=
|
||||
"http://www.boost.org/people/kevlin_henney.htm">Kevlin Henney</a> is now superseeded by the <a href="../numeric/conversion/doc/html/index.html">Boost Numeric Conversion Library</a></p>
|
||||
|
@ -1,5 +1,5 @@
|
||||
// boost polymorphic_pointer_cast.hpp header file ----------------------------------------------//
|
||||
// (C) Copyright Boris Rasin 2014.
|
||||
// (C) Copyright Boris Rasin and Antony Polukhin 2014.
|
||||
// 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)
|
||||
@ -61,6 +61,17 @@ namespace boost
|
||||
return static_pointer_cast<Target> (x);
|
||||
}
|
||||
|
||||
template <typename Target, typename Source>
|
||||
inline typename detail::static_pointer_cast_result<Target, Source>::type
|
||||
polymorphic_pointer_cast (const Source& x)
|
||||
{
|
||||
typename detail::static_pointer_cast_result<Target, Source>::type tmp
|
||||
= dynamic_pointer_cast<Target> (x);
|
||||
if ( !tmp ) boost::throw_exception( std::bad_cast() );
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_CONVERSION_POLYMORPHIC_POINTER_CAST_HPP
|
||||
|
@ -1,10 +1,11 @@
|
||||
//
|
||||
// Test boost::polymorphic_cast, boost::polymorphic_downcast
|
||||
// Test boost::polymorphic_cast, boost::polymorphic_downcast and
|
||||
// boost::polymorphic_pointer_cast, boost::polymorphic_pointer_downcast
|
||||
//
|
||||
// Copyright 1999 Beman Dawes
|
||||
// Copyright 1999 Dave Abrahams
|
||||
// Copyright 2014 Peter Dimov
|
||||
// Copyright 2014 Boris Rasin
|
||||
// Copyright 2014 Boris Rasin, Antony Polukhin
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
@ -103,6 +104,67 @@ static void test_polymorphic_cast()
|
||||
delete base;
|
||||
}
|
||||
|
||||
static void test_polymorphic_pointer_cast()
|
||||
{
|
||||
Base * base = new Derived;
|
||||
|
||||
Derived * derived;
|
||||
|
||||
try
|
||||
{
|
||||
derived = boost::polymorphic_pointer_cast<Derived>( base );
|
||||
|
||||
BOOST_TEST( derived != 0 );
|
||||
|
||||
if( derived != 0 )
|
||||
{
|
||||
BOOST_TEST_EQ( derived->kind(), "Derived" );
|
||||
}
|
||||
}
|
||||
catch( std::bad_cast const& )
|
||||
{
|
||||
BOOST_ERROR( "boost::polymorphic_pointer_cast<Derived>( base ) threw std::bad_cast" );
|
||||
}
|
||||
|
||||
Base2 * base2;
|
||||
|
||||
try
|
||||
{
|
||||
base2 = boost::polymorphic_pointer_cast<Base2>( base ); // crosscast
|
||||
|
||||
BOOST_TEST( base2 != 0 );
|
||||
|
||||
if( base2 != 0 )
|
||||
{
|
||||
BOOST_TEST_EQ( base2->kind2(), "Base2" );
|
||||
}
|
||||
}
|
||||
catch( std::bad_cast const& )
|
||||
{
|
||||
BOOST_ERROR( "boost::polymorphic_pointer_cast<Base2>( base ) threw std::bad_cast" );
|
||||
}
|
||||
|
||||
boost::shared_ptr<Base> sp_base( base );
|
||||
boost::shared_ptr<Base2> sp_base2;
|
||||
try
|
||||
{
|
||||
sp_base2 = boost::polymorphic_pointer_cast<Base2>( sp_base ); // crosscast
|
||||
|
||||
BOOST_TEST( sp_base2 != 0 );
|
||||
|
||||
if( sp_base2 != 0 )
|
||||
{
|
||||
BOOST_TEST_EQ( base2->kind2(), "Base2" );
|
||||
}
|
||||
}
|
||||
catch( std::bad_cast const& )
|
||||
{
|
||||
BOOST_ERROR( "boost::polymorphic_pointer_cast<Base2>( sp_base ) threw std::bad_cast" );
|
||||
}
|
||||
|
||||
// we do not `delete base;` because sahred_ptr is holding base
|
||||
}
|
||||
|
||||
static void test_polymorphic_downcast()
|
||||
{
|
||||
Base * base = new Derived;
|
||||
@ -194,6 +256,21 @@ static void test_polymorphic_cast_fail()
|
||||
delete base;
|
||||
}
|
||||
|
||||
static void test_polymorphic_pointer_cast_fail()
|
||||
{
|
||||
Base * base = new Base;
|
||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_cast<Derived>( base ), std::bad_cast );
|
||||
delete base;
|
||||
|
||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_cast<Derived>( boost::shared_ptr<Base>(new Base) ), std::bad_cast );
|
||||
|
||||
#ifndef BOOST_NO_CXX11_SMART_PTR
|
||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_cast<Derived>( std::shared_ptr<Base>(new Base) ), std::bad_cast );
|
||||
#endif
|
||||
|
||||
BOOST_TEST_THROWS( boost::polymorphic_pointer_cast<Derived>( boost::intrusive_ptr<Base>(new Base) ), std::bad_cast );
|
||||
}
|
||||
|
||||
static void test_polymorphic_downcast_fail()
|
||||
{
|
||||
Base * base = new Base;
|
||||
@ -270,11 +347,13 @@ static void test_polymorphic_pointer_downcast_intrusive_fail()
|
||||
int main()
|
||||
{
|
||||
test_polymorphic_cast();
|
||||
test_polymorphic_pointer_cast();
|
||||
test_polymorphic_downcast();
|
||||
test_polymorphic_pointer_downcast_builtin();
|
||||
test_polymorphic_pointer_downcast_boost_shared();
|
||||
test_polymorphic_pointer_downcast_intrusive();
|
||||
test_polymorphic_cast_fail();
|
||||
test_polymorphic_pointer_cast_fail();
|
||||
test_polymorphic_downcast_fail();
|
||||
test_polymorphic_pointer_downcast_builtin_fail();
|
||||
test_polymorphic_pointer_downcast_boost_shared_fail();
|
||||
|
Reference in New Issue
Block a user