Add overloads for std::shared_ptr to pointer casts

This commit is contained in:
Karolin Varner
2015-12-17 13:47:00 +01:00
parent 2185c4f005
commit 6b787f1cec
4 changed files with 169 additions and 2 deletions

View File

@@ -42,4 +42,34 @@ inline T* reinterpret_pointer_cast(U *ptr)
} // namespace boost } // namespace boost
#if !defined( BOOST_NO_CXX11_SMART_PTR )
#include <memory>
namespace boost {
//static_pointer_cast overload for std::shared_ptr
using std::static_pointer_cast;
//dynamic_pointer_cast overload for std::shared_ptr
using std::dynamic_pointer_cast;
//const_pointer_cast overload for std::shared_ptr
using std::const_pointer_cast;
//reinterpret_pointer_cast overload for std::shared_ptr
template<class T, class U> std::shared_ptr<T> reinterpret_pointer_cast(const std::shared_ptr<U> & r ) BOOST_NOEXCEPT
{
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
typedef typename std::shared_ptr<T>::element_type E;
E * p = reinterpret_cast< E* >( r.get() );
return std::shared_ptr<T>( r, p );
}
} // namespace boost
#endif // #if !defined( BOOST_NO_CXX11_SMART_PTR )
#endif //BOOST_POINTER_CAST_HPP #endif //BOOST_POINTER_CAST_HPP

View File

@@ -9,7 +9,7 @@
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. The functions provide a way to write generic pointer castings for raw pointers and std::shared_ptr. 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>
@@ -23,7 +23,7 @@ template&lt;class T, class U&gt;
<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. This way when developing pointer type independent classes, for raw pointers and std::shared_ptr. This way when developing pointer type independent classes,
for example, memory managers or shared memory compatible classes, the same code for example, memory managers or shared memory compatible classes, the same code
can be used for raw and smart pointers.</p> can be used for raw and smart pointers.</p>
<H2><A name="synopsis">Synopsis</A></H2> <H2><A name="synopsis">Synopsis</A></H2>
@@ -47,6 +47,18 @@ template&lt;class T, class U&gt;
inline T* reinterpret_pointer_cast(U *ptr) 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;
inline std::shared_ptr&lt;U&gt; static_pointer_cast(std::shared_ptr&lt;T&gt; ptr);
template&lt;class T, class U&gt;
inline std::shared_ptr&lt;U&gt; dynamic_pointer_cast(std::shared_ptr&lt;T&gt; ptr);
template&lt;class T, class U&gt;
inline std::shared_ptr&lt;U&gt; const_pointer_cast(std::shared_ptr&lt;T&gt; ptr);
template&lt;class T, class U&gt;
inline std::shared_ptr&lt;U&gt; reinterpret_pointer_cast(std::shared_ptr&lt;T&gt; ptr);
} // namespace boost } // namespace boost
</PRE> </PRE>
</BLOCKQUOTE> </BLOCKQUOTE>

View File

@@ -29,6 +29,7 @@ import testing ;
[ compile-fail shared_ptr_compare_fail.cpp ] [ compile-fail shared_ptr_compare_fail.cpp ]
[ run shared_ptr_alloc2_test.cpp ] [ run shared_ptr_alloc2_test.cpp ]
[ run pointer_cast_test.cpp ] [ run pointer_cast_test.cpp ]
[ run cpp11_pointer_cast_test.cpp ]
[ compile pointer_to_other_test.cpp ] [ compile pointer_to_other_test.cpp ]
[ run auto_ptr_rv_test.cpp ] [ run auto_ptr_rv_test.cpp ]
[ run shared_ptr_alias_test.cpp ] [ run shared_ptr_alias_test.cpp ]

View File

@@ -0,0 +1,124 @@
//
// cpp11_pointer_cast_test.cpp - a test for boost/pointer_cast.hpp with std::shared_ptr
//
// Copyright (c) 2016 Karolin Varner
//
// 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)
//
#include <boost/config.hpp>
#include <boost/pointer_cast.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/get_pointer.hpp>
#include <memory>
namespace
{
// Let's create these inheritance relationship:
//
// base base2
// | |
// derived
// |
// derived_derived
//
class base
{
public:
virtual ~base(){}
int filler [5];
};
class base2
{
public:
virtual ~base2(){}
int filler [5];
};
class derived
: public base, public base2
{
int filler [5];
};
class derived_derived
: public derived
{
int filler [5];
};
// And now some simple check functions
#if !defined( BOOST_NO_RTTI )
template <class BasePtr>
bool check_dynamic_pointer_cast(const BasePtr &ptr)
{
//Check that dynamic_pointer_cast versus dynamic_cast
return
//Correct cast with dynamic_pointer_cast
boost::get_pointer(boost::dynamic_pointer_cast<derived>(ptr)) ==
//Correct cast with dynamic_cast
dynamic_cast<derived*>(boost::get_pointer(ptr))
&&
//Incorrect cast with dynamic_pointer_cast
boost::get_pointer(boost::dynamic_pointer_cast<derived_derived>(ptr)) ==
//Incorrect cast with dynamic_cast
dynamic_cast<derived_derived*>(boost::get_pointer(ptr));
}
#endif
template <class BasePtr>
bool check_static_pointer_cast(const BasePtr &ptr)
{
return
//Cast base -> derived -> base2 using static_pointer_cast
boost::get_pointer(
boost::static_pointer_cast<base2>(
boost::static_pointer_cast<derived>(ptr))) ==
//Now the same with static_cast
static_cast<base2*>(static_cast<derived*>(boost::get_pointer(ptr)));
}
template <class BasePtr>
bool check_const_pointer_cast(const BasePtr &ptr)
{
return
//Unconst and const again using const_pointer_cast
boost::get_pointer(
boost::const_pointer_cast<const base>
(boost::const_pointer_cast<base>(ptr))) ==
//Now the same with const_cast
const_cast<const base*>(const_cast<base*>(boost::get_pointer(ptr)));
}
template <class BasePtr>
void check_all_casts(const BasePtr &ptr)
{
#if !defined( BOOST_NO_RTTI )
BOOST_TEST( check_dynamic_pointer_cast( ptr ) );
#endif
BOOST_TEST( check_static_pointer_cast( ptr ) );
BOOST_TEST( check_const_pointer_cast( ptr ) );
}
}
int main()
{
#if !defined( BOOST_NO_CXX11_SMART_PTR )
std::shared_ptr<base> std_shared(new derived);
check_all_casts(std_shared);
#endif
return boost::report_errors();
}