diff --git a/include/boost/polymorphic_cast.hpp b/include/boost/polymorphic_cast.hpp index 70afa6b..802ac9a 100644 --- a/include/boost/polymorphic_cast.hpp +++ b/include/boost/polymorphic_cast.hpp @@ -52,6 +52,9 @@ # include # include # include +# include +# include +# include # include #ifdef BOOST_HAS_PRAGMA_ONCE @@ -79,7 +82,7 @@ namespace boost // polymorphic_downcast ----------------------------------------------------// - // BOOST_ASSERT() checked polymorphic downcast. Crosscasts prohibited. + // BOOST_ASSERT() checked raw pointer polymorphic downcast. Crosscasts prohibited. // WARNING: Because this cast uses BOOST_ASSERT(), it violates // the One Definition Rule if used in multiple translation units @@ -95,6 +98,22 @@ namespace boost return static_cast(x); } + // BOOST_ASSERT() checked reference polymorphic downcast. Crosscasts prohibited. + + // WARNING: Because this cast uses BOOST_ASSERT(), it violates + // the One Definition Rule if used in multiple translation units + // where BOOST_DISABLE_ASSERTS, BOOST_ENABLE_ASSERT_HANDLER + // NDEBUG are defined inconsistently. + + // Contributed by Julien Delacroix + + template + inline typename boost::enable_if_c::value, Target>::type polymorphic_downcast(Source &x) + { + BOOST_ASSERT(dynamic_cast::type *>(&x) == &x); + return static_cast(x); + } + } // namespace boost #endif // BOOST_POLYMORPHIC_CAST_HPP diff --git a/test/polymorphic_cast_test.cpp b/test/polymorphic_cast_test.cpp index d0e527d..5bb0699 100644 --- a/test/polymorphic_cast_test.cpp +++ b/test/polymorphic_cast_test.cpp @@ -172,20 +172,23 @@ static void test_polymorphic_pointer_cast() static void test_polymorphic_downcast() { - Base * base = new Derived; + Base *base_pointer = new Derived; - Derived * derived = boost::polymorphic_downcast( base ); + // test raw pointer cast + Derived *derived_pointer = boost::polymorphic_downcast(base_pointer); - BOOST_TEST( derived != 0 ); + BOOST_TEST(derived_pointer != 0); - if( derived != 0 ) + if (derived_pointer != 0) { - BOOST_TEST_EQ( derived->kind(), "Derived" ); + BOOST_TEST_EQ(derived_pointer->kind(), "Derived"); } - // polymorphic_downcast can't do crosscasts + // test reference cast + Derived& derived_ref = boost::polymorphic_downcast(*base_pointer); + BOOST_TEST_EQ(derived_ref.kind(), "Derived"); - delete base; + delete base_pointer; } static void test_polymorphic_pointer_downcast_builtin() @@ -278,17 +281,32 @@ static void test_polymorphic_pointer_cast_fail() static void test_polymorphic_downcast_fail() { - Base * base = new Base; + Base * base_pointer = new Base; - int old_count = assertion_failed_count; - expect_assertion = true; + { + // test raw pointer cast - BOOST_TEST_THROWS( boost::polymorphic_downcast( base ), expected_assertion ); // should assert + int old_count = assertion_failed_count; + expect_assertion = true; - BOOST_TEST_EQ( assertion_failed_count, old_count + 1 ); - expect_assertion = false; + BOOST_TEST_THROWS(boost::polymorphic_downcast(base_pointer), expected_assertion); // should assert - delete base; + BOOST_TEST_EQ(assertion_failed_count, old_count + 1); + expect_assertion = false; + } + { + // test reference cast + + int old_count = assertion_failed_count; + expect_assertion = true; + + BOOST_TEST_THROWS(boost::polymorphic_downcast(*base_pointer), expected_assertion); // should assert + + BOOST_TEST_EQ(assertion_failed_count, old_count + 1); + expect_assertion = false; + } + + delete base_pointer; } static void test_polymorphic_pointer_downcast_builtin_fail()