diff --git a/include/boost/pointer_cast.hpp b/include/boost/pointer_cast.hpp index 6e532eb..3c65cac 100644 --- a/include/boost/pointer_cast.hpp +++ b/include/boost/pointer_cast.hpp @@ -42,4 +42,34 @@ inline T* reinterpret_pointer_cast(U *ptr) } // namespace boost +#if !defined( BOOST_NO_CXX11_SMART_PTR ) + +#include + +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 std::shared_ptr reinterpret_pointer_cast(const std::shared_ptr & r ) BOOST_NOEXCEPT +{ + (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename std::shared_ptr::element_type E; + + E * p = reinterpret_cast< E* >( r.get() ); + return std::shared_ptr( r, p ); +} + +} // namespace boost + +#endif // #if !defined( BOOST_NO_CXX11_SMART_PTR ) + #endif //BOOST_POINTER_CAST_HPP diff --git a/pointer_cast.html b/pointer_cast.html index 2ab0859..4e52cf0 100644 --- a/pointer_cast.html +++ b/pointer_cast.html @@ -9,7 +9,7 @@ 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. The functions + provide a way to write generic pointer castings for raw pointers and std::shared_ptr. The functions are defined in boost/pointer_cast.hpp.

There is test/example code in pointer_cast_test.cpp.

Rationale

@@ -23,7 +23,7 @@ template<class T, class U>

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. 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 can be used for raw and smart pointers.

Synopsis

@@ -46,6 +46,18 @@ inline T* const_pointer_cast(U *ptr) template<class T, class U> 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); + +template<class T, class U> +inline std::shared_ptr<U> dynamic_pointer_cast(std::shared_ptr<T> ptr); + +template<class T, class U> +inline std::shared_ptr<U> const_pointer_cast(std::shared_ptr<T> ptr); + +template<class T, class U> +inline std::shared_ptr<U> reinterpret_pointer_cast(std::shared_ptr<T> ptr); } // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d965bfd..6eb4c89 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -29,6 +29,7 @@ import testing ; [ compile-fail shared_ptr_compare_fail.cpp ] [ run shared_ptr_alloc2_test.cpp ] [ run pointer_cast_test.cpp ] + [ run cpp11_pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] [ run auto_ptr_rv_test.cpp ] [ run shared_ptr_alias_test.cpp ] diff --git a/test/cpp11_pointer_cast_test.cpp b/test/cpp11_pointer_cast_test.cpp new file mode 100644 index 0000000..a937708 --- /dev/null +++ b/test/cpp11_pointer_cast_test.cpp @@ -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 +#include +#include +#include + +#include + +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 +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(ptr)) == + //Correct cast with dynamic_cast + dynamic_cast(boost::get_pointer(ptr)) + && + //Incorrect cast with dynamic_pointer_cast + boost::get_pointer(boost::dynamic_pointer_cast(ptr)) == + //Incorrect cast with dynamic_cast + dynamic_cast(boost::get_pointer(ptr)); +} + +#endif + +template +bool check_static_pointer_cast(const BasePtr &ptr) +{ + return + //Cast base -> derived -> base2 using static_pointer_cast + boost::get_pointer( + boost::static_pointer_cast( + boost::static_pointer_cast(ptr))) == + //Now the same with static_cast + static_cast(static_cast(boost::get_pointer(ptr))); +} + +template +bool check_const_pointer_cast(const BasePtr &ptr) +{ + return + //Unconst and const again using const_pointer_cast + boost::get_pointer( + boost::const_pointer_cast + (boost::const_pointer_cast(ptr))) == + //Now the same with const_cast + const_cast(const_cast(boost::get_pointer(ptr))); +} + +template +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 std_shared(new derived); + check_all_casts(std_shared); +#endif + + return boost::report_errors(); +} +