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:
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();
}
From 582fc91adb10fa4c6ea124d36b34cbfdfc760a45 Mon Sep 17 00:00:00 2001
From: Boris Rasin
Date: Sun, 9 Nov 2014 15:37:56 +0200
Subject: [PATCH 2/2] add more tests and documentation example for
polymorphic_pointer_downcast
---
cast.htm | 24 +++++++
test/polymorphic_cast_test.cpp | 112 +++++++++++++++++++++++++++++++--
2 files changed, 131 insertions(+), 5 deletions(-)
diff --git a/cast.htm b/cast.htm
index 860ac17..d913d72 100644
--- a/cast.htm
+++ b/cast.htm
@@ -134,6 +134,30 @@ void f( Fruit * fruit ) {
+
polymorphic_pointer_downcast example
+
+
+
#include <boost/polymorphic_cast.hpp>
+
+class Fruit { public: virtual ~Fruit(){} };
+class Banana : public Fruit {};
+
+// use one of these:
+
+typedef Fruit* FruitPtr;
+typedef std::shared_ptr<Fruit> FruitPtr;
+typedef boost::shared_ptr<Fruit> FruitPtr;
+typedef boost::intrusive_ptr<Fruit> FruitPtr;
+
+void f(FruitPtr fruit)
+{
+ // ... logic which leads us to believe it is a banana
+ auto banana = boost::polymorphic_pointer_downcast<Banana>(fruit);
+ ...
+}
+