From 3e2ac10e94c7bc8d54915072676226371ef2b0a7 Mon Sep 17 00:00:00 2001 From: Chris Glover Date: Sun, 11 Dec 2016 15:38:34 -0500 Subject: [PATCH] Add rvalue versions of static_pointer_cast, const_pointer_cast, dynamic_pointer_cast, reinterpret_pointer_cast. Aligns with proposed addition to std:: here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0390r0.htm --- include/boost/smart_ptr/shared_ptr.hpp | 44 +++++++++++ test/Jamfile.v2 | 1 + test/shared_ptr_rv_pointer_cast_test.cpp | 96 ++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 test/shared_ptr_rv_pointer_cast_test.cpp diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index deb3fec..e33707b 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -883,6 +883,50 @@ template shared_ptr reinterpret_pointer_cast( shared_ptr return shared_ptr( r, p ); } +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + +template shared_ptr static_pointer_cast( shared_ptr && r ) BOOST_NOEXCEPT +{ + (void) static_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename shared_ptr::element_type E; + + E * p = static_cast< E* >( r.get() ); + return shared_ptr( std::move(r), p ); +} + +template shared_ptr const_pointer_cast( shared_ptr && r ) BOOST_NOEXCEPT +{ + (void) const_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename shared_ptr::element_type E; + + E * p = const_cast< E* >( r.get() ); + return shared_ptr( std::move(r), p ); +} + +template shared_ptr dynamic_pointer_cast( shared_ptr && r ) BOOST_NOEXCEPT +{ + (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename shared_ptr::element_type E; + + E * p = dynamic_cast< E* >( r.get() ); + return p? shared_ptr( std::move(r), p ): shared_ptr(); +} + +template shared_ptr reinterpret_pointer_cast( shared_ptr && r ) BOOST_NOEXCEPT +{ + (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename shared_ptr::element_type E; + + E * p = reinterpret_cast< E* >( r.get() ); + return shared_ptr( std::move(r), p ); +} + +#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + // get_pointer() enables boost::mem_fn to recognize shared_ptr template inline typename shared_ptr::element_type * get_pointer(shared_ptr const & p) BOOST_NOEXCEPT diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a9546db..b30eead 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -34,6 +34,7 @@ import testing ; [ run auto_ptr_rv_test.cpp ] [ run shared_ptr_alias_test.cpp ] [ run shared_ptr_rv_test.cpp ] + [ run shared_ptr_rv_pointer_cast_test.cpp ] [ run shared_ptr_move_test.cpp ] [ run shared_ptr_alias_move_test.cpp ] [ compile-fail shared_ptr_pv_fail.cpp ] diff --git a/test/shared_ptr_rv_pointer_cast_test.cpp b/test/shared_ptr_rv_pointer_cast_test.cpp new file mode 100644 index 0000000..0c4ea8b --- /dev/null +++ b/test/shared_ptr_rv_pointer_cast_test.cpp @@ -0,0 +1,96 @@ +// +// shared_ptr_rv_pointer_cast_test.cpp +// +// Copyright (c) 2016 Chris Glover +// +// 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 + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + +struct X +{}; + +struct Y: public X +{}; + +struct U +{ + virtual ~U() {} +}; + +struct V: public U +{}; + +struct W : public U +{}; + +int main() +{ + { + boost::shared_ptr px(new Y); + + boost::shared_ptr py1 = boost::static_pointer_cast(px); + boost::shared_ptr py2 = boost::static_pointer_cast(std::move(px)); + BOOST_TEST(!px); + BOOST_TEST(px.use_count() == 0); + BOOST_TEST(py1.get() == py2.get()); + BOOST_TEST(!(py1 < py2 || py2 < py1)); + BOOST_TEST(py1.use_count() == 2); + BOOST_TEST(py2.use_count() == 2); + } + + { + boost::shared_ptr px(new int); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + boost::shared_ptr px3 = boost::const_pointer_cast(std::move(px)); + BOOST_TEST(!px); + BOOST_TEST(px.use_count() == 0); + BOOST_TEST(px2.get() == px3.get()); + BOOST_TEST(!(px2 < px3 || px2 < px3)); + BOOST_TEST(px2.use_count() == 2); + BOOST_TEST(px3.use_count() == 2); + } + +#if !defined( BOOST_NO_RTTI ) + { + boost::shared_ptr pu(new V); + + boost::shared_ptr pv1 = boost::dynamic_pointer_cast(pu); + boost::shared_ptr pv2 = boost::dynamic_pointer_cast(std::move(pu)); + BOOST_TEST(!pu); + BOOST_TEST(pu.use_count() == 0); + BOOST_TEST(pv1.get() == pv2.get()); + BOOST_TEST(!(pv1 < pv2 || pv2 < pv1)); + BOOST_TEST(pv1.use_count() == 2); + BOOST_TEST(pv2.use_count() == 2); + } + + { + boost::shared_ptr pu(new V); + boost::shared_ptr pw = boost::dynamic_pointer_cast(std::move(pu)); + BOOST_TEST(!pw); + BOOST_TEST(pu); + } +#endif // !defined( BOOST_NO_RTTI ) + + return boost::report_errors(); +} + +#else // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + +int main() +{ + return 0; +} + + +#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + +