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:
Julien DELACROIX
2019-12-09 08:51:10 +01:00
parent 9d4a518e74
commit e130cd860c
2 changed files with 52 additions and 15 deletions
+20 -1
View File
@@ -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