diff --git a/cast.htm b/cast.htm index 208b960..860ac17 100644 --- a/cast.htm +++ b/cast.htm @@ -26,10 +26,11 @@

Cast Functions

-

The header boost/polymorphic_cast.hpp provides - polymorphic_cast and polymorphic_downcast function templates designed to - complement the C++ built-in casts.

+

The header boost/polymorphic_cast.hpp provides + polymorphic_cast, + polymorphic_downcast and + polymorphic_pointer_downcast + function templates designed to complement the C++ built-in casts.

The program cast_test.cpp can be used to verify these function templates work as expected.

@@ -88,7 +89,13 @@ whether a given interface is supported; in that case a return of 0 isn't an error condition.

-

polymorphic_cast and polymorphic_downcast synopsis

+

While polymorphic_downcast works with built-in pointer types only, + polymorphic_pointer_downcast is a more generic version + with support for any pointer type for which the following expressions would be valid:

+   static_pointer_cast<Derived>(p);
  dynamic_pointer_cast<Derived>(p);


+ This includes C++ built-in pointers, std::shared_ptr, boost::shared_ptr, boost::intrusive_ptr, etc.

+ +

polymorphic_cast, polymorphic_downcast and polymorphic_pointer_downcast synopsis

namespace boost {
@@ -103,6 +110,11 @@ inline Derived polymorphic_downcast(Base* x);
 // Effects: assert( dynamic_cast<Derived>(x) == x );
 // Returns: static_cast<Derived>(x)
 
+template <class Derived, class Base>
+inline auto polymorphic_pointer_downcast(Base x);
+// Effects: assert( dynamic_pointer_cast<Derived>(x) == x );
+// Returns: static_pointer_cast<Derived>(x)
+
 }
 
@@ -127,9 +139,11 @@ void f( Fruit * fruit ) {

polymorphic_cast was suggested by Bjarne Stroustrup in "The C++ Programming Language".
polymorphic_downcast was contributed by Dave Abrahams.
+ "http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams.
+ polymorphic_pointer_downcast was contributed by Boris Rasin.
An old - numeric_cast
that was contributed by numeric_cast that was contributed by Kevlin Henney is now superseeded by the Boost Numeric Conversion Library


diff --git a/include/boost/polymorphic_cast.hpp b/include/boost/polymorphic_cast.hpp index 03013c7..7221ade 100644 --- a/include/boost/polymorphic_cast.hpp +++ b/include/boost/polymorphic_cast.hpp @@ -1,6 +1,7 @@ // boost polymorphic_cast.hpp header file ----------------------------------------------// // (C) Copyright Kevlin Henney and Dave Abrahams 1999. +// (C) Copyright Boris Rasin 2014. // 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) @@ -8,6 +9,7 @@ // See http://www.boost.org/libs/conversion for Documentation. // Revision History +// 08 Nov 14 Add polymorphic_pointer_downcast (Boris Rasin) // 09 Jun 14 "cast.hpp" was renamed to "polymorphic_cast.hpp" and // inclusion of numeric_cast was removed (Antony Polukhin) // 23 Jun 05 numeric_cast removed and redirected to the new verion (Fernando Cacciola) @@ -47,6 +49,9 @@ # include # include +# include +# include +# include # include namespace boost @@ -86,6 +91,41 @@ namespace boost return static_cast(x); } +// polymorphic_pointer_downcast --------------------------------------------// + + // BOOST_ASSERT() checked polymorphic downcast. Crosscasts prohibited. + // Supports any type with static_pointer_cast/dynamic_pointer_cast functions: + // built-in pointers, std::shared_ptr, boost::shared_ptr, boost::intrusive_ptr, etc. + + // 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 Boris Rasin + + namespace detail + { + template + struct static_pointer_cast_result + { +#ifdef BOOST_NO_CXX11_DECLTYPE + BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, static_pointer_cast(boost::declval())) + typedef typename nested::type type; +#else + typedef decltype(static_pointer_cast(boost::declval())) type; +#endif + }; + } + + template + inline typename detail::static_pointer_cast_result::type + polymorphic_pointer_downcast (const Source& x) + { + BOOST_ASSERT(dynamic_pointer_cast (x) == x); + return static_pointer_cast (x); + } + } // namespace boost #endif // BOOST_POLYMORPHIC_CAST_HPP diff --git a/index.html b/index.html index fbfe63a..6dc9a96 100644 --- a/index.html +++ b/index.html @@ -27,8 +27,8 @@ Standard's built-in casts.

Conversion Library is supplied by several headers:

    -
  • The boost/cast header provides polymorphic_cast<> - and polymorphic_downcast<> to perform safe casting between +
  • The boost/cast header provides polymorphic_cast<>, + polymorphic_downcast<> and polymorphic_pointer_downcast<> to perform safe casting between polymorphic types.
  • The boost/lexical_cast header provides lexical_cast<> diff --git a/test/polymorphic_cast_test.cpp b/test/polymorphic_cast_test.cpp index b3f1397..b8a500c 100644 --- a/test/polymorphic_cast_test.cpp +++ b/test/polymorphic_cast_test.cpp @@ -4,6 +4,7 @@ // Copyright 1999 Beman Dawes // Copyright 1999 Dave Abrahams // Copyright 2014 Peter Dimov +// Copyright 2014 Boris Rasin // // Distributed under the Boost Software License, Version 1.0. // @@ -115,6 +116,24 @@ static void test_polymorphic_downcast() delete base; } +static void test_polymorphic_pointer_downcast() +{ + Base * base = new Derived; + + Derived * derived = boost::polymorphic_pointer_downcast( base ); + + BOOST_TEST( derived != 0 ); + + if( derived != 0 ) + { + BOOST_TEST_EQ( derived->kind(), "Derived" ); + } + + // polymorphic_pointer_downcast can't do crosscasts + + delete base; +} + static void test_polymorphic_cast_fail() { Base * base = new Base; @@ -139,12 +158,29 @@ static void test_polymorphic_downcast_fail() delete base; } +static void test_polymorphic_pointer_downcast_fail() +{ + Base * base = new Base; + + int old_count = assertion_failed_count; + expect_assertion = true; + + boost::polymorphic_pointer_downcast( base ); // should assert + + BOOST_TEST_EQ( assertion_failed_count, old_count + 1 ); + expect_assertion = false; + + delete base; +} + int main() { test_polymorphic_cast(); test_polymorphic_downcast(); + test_polymorphic_pointer_downcast(); test_polymorphic_cast_fail(); test_polymorphic_downcast_fail(); + test_polymorphic_pointer_downcast_fail(); return boost::report_errors(); }