From 190c06e25d026f68696bd7e16443f7e82e24814c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 10 Sep 2016 17:55:14 +0300 Subject: [PATCH] Add tests for unique_ptr casts. --- include/boost/pointer_cast.hpp | 17 ++- test/Jamfile.v2 | 3 + test/pointer_cast_test2.cpp | 214 +++++++++++++++++++++++++++++++++ test/pointer_cast_test3.cpp | 49 ++++++++ 4 files changed, 278 insertions(+), 5 deletions(-) create mode 100644 test/pointer_cast_test2.cpp create mode 100644 test/pointer_cast_test3.cpp diff --git a/include/boost/pointer_cast.hpp b/include/boost/pointer_cast.hpp index 6a5af8b..e5cd41f 100644 --- a/include/boost/pointer_cast.hpp +++ b/include/boost/pointer_cast.hpp @@ -7,11 +7,11 @@ // ////////////////////////////////////////////////////////////////////////////// -#include - #ifndef BOOST_POINTER_CAST_HPP #define BOOST_POINTER_CAST_HPP +#include + namespace boost { //static_pointer_cast overload for raw pointers @@ -90,8 +90,11 @@ template std::shared_ptr reinterpret_pointer_cast(const std //static_pointer_cast overload for std::unique_ptr template std::unique_ptr static_pointer_cast( std::unique_ptr && r ) BOOST_NOEXCEPT { + typedef typename std::unique_ptr::element_type E; + detail::assert_safe_moving_upcast(); - return std::unique_ptr( static_cast( r.release() ) ); + + return std::unique_ptr( static_cast( r.release() ) ); } //dynamic_pointer_cast overload for std::unique_ptr @@ -107,13 +110,17 @@ template std::unique_ptr dynamic_pointer_cast( std::unique_ //const_pointer_cast overload for std::unique_ptr template std::unique_ptr const_pointer_cast( std::unique_ptr && r ) BOOST_NOEXCEPT { - return std::unique_ptr( const_cast( r.release() ) ); + typedef typename std::unique_ptr::element_type E; + + return std::unique_ptr( const_cast( r.release() ) ); } //reinterpret_pointer_cast overload for std::unique_ptr template std::unique_ptr reinterpret_pointer_cast( std::unique_ptr && r ) BOOST_NOEXCEPT { - return std::unique_ptr( reinterpret_cast( r.release() ) ); + typedef typename std::unique_ptr::element_type E; + + return std::unique_ptr( reinterpret_cast( r.release() ) ); } } // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6eb4c89..596e167 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -186,5 +186,8 @@ import testing ; [ run sp_hash_test2.cpp ] [ run sp_hash_test3.cpp ] + + [ run pointer_cast_test2.cpp ] + [ run pointer_cast_test3.cpp ] ; } diff --git a/test/pointer_cast_test2.cpp b/test/pointer_cast_test2.cpp new file mode 100644 index 0000000..a74058b --- /dev/null +++ b/test/pointer_cast_test2.cpp @@ -0,0 +1,214 @@ +// +// pointer_cast_test2.cpp - a test for unique_ptr casts +// +// Copyright 2016 Peter Dimov +// +// 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 + +#if defined( BOOST_NO_CXX11_SMART_PTR ) + +int main() +{ + return 0; +} + +#else + +#include +#include +#include + +struct B +{ + virtual ~B() + { + } +}; + +struct D: B +{ +}; + +static void test_static_cast() +{ + { + std::unique_ptr p1( new int ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new int ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new int[ 1 ] ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new int[ 1 ] ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new D ); + D * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new D ); + B * q1 = p1.get(); + + std::unique_ptr p2 = boost::static_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } +} + +static void test_const_cast() +{ + { + std::unique_ptr p1( new int ); + int const * q1 = p1.get(); + + std::unique_ptr p2 = boost::const_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new int ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::const_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new int[ 1 ] ); + int * q1 = p1.get(); + + std::unique_ptr p2 = boost::const_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } +} + +static void test_dynamic_cast() +{ + { + std::unique_ptr p1( new D ); + D * q1 = p1.get(); + + std::unique_ptr p2 = boost::dynamic_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } + + { + std::unique_ptr p1( new D ); + B * q1 = p1.get(); + + std::unique_ptr p2 = boost::dynamic_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } +} + +static void test_reinterpret_cast() +{ + { + std::unique_ptr p1( new int ); + void * q1 = p1.get(); + + std::unique_ptr p2 = boost::reinterpret_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + + p1 = boost::reinterpret_pointer_cast( std::move( p2 ) ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST_EQ( p1.get(), q1 ); + } + + { + std::unique_ptr p1( new int ); + void * q1 = p1.get(); + + std::unique_ptr p2 = boost::reinterpret_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + + p1 = boost::reinterpret_pointer_cast( std::move( p2 ) ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST_EQ( p1.get(), q1 ); + } + + { + std::unique_ptr p1( new int[ 1 ] ); + void * q1 = p1.get(); + + std::unique_ptr p2 = boost::reinterpret_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + + p1 = boost::reinterpret_pointer_cast( std::move( p2 ) ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST_EQ( p1.get(), q1 ); + } +} + +int main() +{ + test_static_cast(); + test_const_cast(); + test_dynamic_cast(); + test_reinterpret_cast(); + + return boost::report_errors(); +} + +#endif diff --git a/test/pointer_cast_test3.cpp b/test/pointer_cast_test3.cpp new file mode 100644 index 0000000..c2b19f9 --- /dev/null +++ b/test/pointer_cast_test3.cpp @@ -0,0 +1,49 @@ +// +// pointer_cast_test3.cpp - a test for unique_ptr casts +// +// Copyright 2016 Peter Dimov +// +// 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 + +#if defined( BOOST_NO_CXX11_SMART_PTR ) + +int main() +{ + return 0; +} + +#else + +#include +#include +#include + +// This test fails on msvc-10.0, 11.0, 12.0 because +// their unique_ptr implementation can't compile the +// initialization of p1 + +static void test_const_cast() +{ + { + std::unique_ptr p1( new int[ 1 ] ); + int const * q1 = p1.get(); + + std::unique_ptr p2 = boost::const_pointer_cast( std::move( p1 ) ); + + BOOST_TEST( p1.get() == 0 ); + BOOST_TEST_EQ( p2.get(), q1 ); + } +} + +int main() +{ + test_const_cast(); + return boost::report_errors(); +} + +#endif