forked from boostorg/conversion
boost::polymorphic_downcast only supports raw pointer cast, which is a gap compared to static_cast.
To make it clear: Base* base = new Base(); static_cast<Derived*>(base) ===> OK static_cast<Derived&>(*base) ===> OK boost::polymorphic_downcast<Derived*>(base) ===> OK boost::polymorphic_downcast<Derived&>(*base) ===> IMPOSSIBLE boost::polymorphic_downcast being a kind of "debug-safe version" of static_cast, it should provide the same capabilities. This patch extend boost::polymorphic_downcast to support references just like static_cast does. This is achieved by introducing a partial specialization for references. Unit tests have been updated accordingly.
This commit is contained in:
@ -52,6 +52,9 @@
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/assert.hpp>
|
||||
# include <boost/throw_exception.hpp>
|
||||
# include <boost/type_traits/is_reference.hpp>
|
||||
# include <boost/type_traits/remove_reference.hpp>
|
||||
# include <boost/utility/enable_if.hpp>
|
||||
# include <typeinfo>
|
||||
|
||||
#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<Target>(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 <class Target, class Source>
|
||||
inline typename boost::enable_if_c<boost::is_reference<Target>::value, Target>::type polymorphic_downcast(Source &x)
|
||||
{
|
||||
BOOST_ASSERT(dynamic_cast<typename boost::remove_reference<Target>::type *>(&x) == &x);
|
||||
return static_cast<Target>(x);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_POLYMORPHIC_CAST_HPP
|
||||
|
@ -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<Derived*>( base );
|
||||
// test raw pointer cast
|
||||
Derived *derived_pointer = boost::polymorphic_downcast<Derived *>(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<Derived&>(*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<Derived*>( 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<Derived *>(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<Derived &>(*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()
|
||||
|
Reference in New Issue
Block a user