// // cpp11_pointer_cast_test.cpp - a test for boost/pointer_cast.hpp with std::shared_ptr and std::unique_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 #include #include #include #if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) \ || defined( BOOST_NO_CXX11_HDR_FUNCTIONAL ) \ || defined( BOOST_NO_CXX11_HDR_UTILITY ) \ || defined( BOOST_NO_CXX11_LAMBDAS ) \ || defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // We expect all the features or none of the features to be // available, since we should be on C++11 int main() { return 0; } #else 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_copy_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 ) ); } #if !defined( BOOST_NO_RTTI ) template bool check_dynamic_moving_pointer_cast(std::function f) { BasePtr smart1 = f(), smart2 = f(); derived* expect1 = dynamic_cast(boost::get_pointer(smart1)); derived_derived* expect2 = dynamic_cast(boost::get_pointer(smart2)); //Check that dynamic_pointer_cast versus dynamic_cast return //Correct cast with dynamic_pointer_cast boost::get_pointer(boost::dynamic_pointer_cast( std::move(smart1) )) == expect1 && //Incorrect cast with dynamic_pointer_cast boost::get_pointer(boost::dynamic_pointer_cast( std::move(smart2) )) == expect2; } #endif template bool check_static_moving_pointer_cast(std::function f) { BasePtr smart = f(); base2 *expect = static_cast(static_cast(boost::get_pointer(smart))); return //Cast base -> derived -> base2 using static_pointer_cast boost::get_pointer( boost::static_pointer_cast( boost::static_pointer_cast( std::move(smart) ))) == //Now the same with static_cast expect; } template bool check_const_moving_pointer_cast(std::function f) { BasePtr smart = f(); const base *expect = const_cast(const_cast(boost::get_pointer(smart))); return //Unconst and const again using const_pointer_cast boost::get_pointer( boost::const_pointer_cast (boost::const_pointer_cast( std::move(smart) ))) == //Now the same with const_cast expect; } template void check_all_moving_casts(std::function f) { #if !defined( BOOST_NO_RTTI ) BOOST_TEST( check_dynamic_moving_pointer_cast( f ) ); #endif BOOST_TEST( check_static_moving_pointer_cast( f ) ); BOOST_TEST( check_const_moving_pointer_cast( f ) ); } } int main() { std::shared_ptr std_shared(new derived); boost::shared_ptr boost_shared(new derived); base *plain = boost_shared.get(); // plain & boost::shared_ptr moving pointer_cast checks; there // is no specific handleing for those types at the moment; this // test just makes sure they won't break when std::move() is used // in generic code check_all_moving_casts>([&boost_shared]() { return boost_shared; }); check_all_moving_casts([plain]() { return plain; }); // std::shared_ptr casts check_all_copy_casts(std_shared); check_all_moving_casts>([&std_shared]() { return std_shared; }); // std::unique_ptr casts check_all_moving_casts>([]() { return std::unique_ptr(new derived); }); return boost::report_errors(); } #endif