From 0dd3285d5668ca25da0858ca9cce80a972a5d6dd Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Wed, 6 Feb 2002 19:42:04 +0000 Subject: [PATCH] New casts for smart pointers. [SVN r12743] --- include/boost/shared_ptr.hpp | 23 ++++++++++++++++++++++- include/boost/weak_ptr.hpp | 20 ++++++++++++++++++++ shared_ptr.htm | 24 ++++++++++++++++++++++-- weak_ptr.htm | 24 ++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index e6411c3..c13c3a8 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -43,6 +43,7 @@ namespace detail struct static_cast_tag {}; struct dynamic_cast_tag {}; +struct polymorphic_cast_tag {}; template struct shared_ptr_traits { @@ -114,6 +115,15 @@ public: } } + template + shared_ptr(shared_ptr const & r, detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if (px == 0) + { + throw std::bad_cast(); + } + } + #ifndef BOOST_NO_AUTO_PTR template @@ -219,7 +229,7 @@ template inline bool operator<(shared_ptr const & a, shared_ptr()(a.get(), b.get()); } -template void swap(shared_ptr & a, shared_ptr & b) +template inline void swap(shared_ptr & a, shared_ptr & b) { a.swap(b); } @@ -234,6 +244,17 @@ template shared_ptr shared_dynamic_cast(shared_ptr return shared_ptr(r, detail::dynamic_cast_tag()); } +template shared_ptr shared_polymorphic_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::polymorphic_cast_tag()); +} + +template shared_ptr shared_polymorphic_downcast(shared_ptr const & r) +{ + BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); + return shared_static_cast(r); +} + // get_pointer() enables boost::mem_fn to recognize shared_ptr template inline T * get_pointer(shared_ptr const & p) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index f96856a..c96d097 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -73,6 +73,15 @@ public: } } + template + weak_ptr(weak_ptr const & r, detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if (px == 0) + { + throw std::bad_cast(); + } + } + template weak_ptr & operator=(weak_ptr const & r) // never throws { @@ -170,6 +179,17 @@ template weak_ptr shared_dynamic_cast(weak_ptr const & r return weak_ptr(r, detail::dynamic_cast_tag()); } +template weak_ptr shared_polymorphic_cast(weak_ptr const & r) +{ + return weak_ptr(r, detail::polymorphic_cast_tag()); +} + +template weak_ptr shared_polymorphic_downcast(weak_ptr const & r) +{ + BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); + return shared_static_cast(r); +} + // get_pointer() enables boost::mem_fn to recognize weak_ptr template inline T * get_pointer(weak_ptr const & p) diff --git a/shared_ptr.htm b/shared_ptr.htm index 42e23fe..0e9d426 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -97,6 +97,10 @@ function must be passed in, or the pointed-to object must have a trivial destruc shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws template<typename T, typename U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r); + template<typename T, typename U> + shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r); + template<typename T, typename U> + shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws } @@ -244,7 +248,7 @@ Provided as an aid to generic programming.

shared_static_cast

template<typename T, typename U>
-  shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws
+ shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws

Perform a static_cast on the stored pointer, returning another shared_ptr. The resulting smart pointer will share its use count with the original pointer.

Note that the seemingly equivalent expression

@@ -253,7 +257,7 @@ The resulting smart pointer will share its use count with the original pointer.<

shared_dynamic_cast

template<typename T, typename U>
-  shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);
+ shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);

Perform a dynamic_cast on the stored pointer, returning another shared_ptr. The resulting smart pointer will share its use count with the original pointer unless the result of the cast is 0. The only exception which may be thrown is std::bad_alloc, which may be thrown during the @@ -263,6 +267,22 @@ cast has no effect.

shared_ptr<T>(dynamic_cast<T*>(r.get()))

will eventually result in undefined behavior, attempting to delete the same object twice.

+

shared_polymorphic_cast

+
template<typename T, typename U>
+  shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r);
+

Perform a polymorphic_cast on the stored pointer, +returning another shared_ptr. +The resulting smart pointer will share its use count with the original pointer. +The only exception which may be thrown is std::bad_cast, if the pointer type can not be converted. +If an exception is thrown, the cast has no effect.

+ +

shared_polymorphic_downcast

+
template<typename T, typename U>
+  shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws
+

Perform a polymorphic_downcast on the stored pointer, +returning another shared_ptr. +The resulting smart pointer will share its use count with the original pointer.

+

Example

See shared_ptr_example.cpp for a complete example program. diff --git a/weak_ptr.htm b/weak_ptr.htm index a28232b..ccedf19 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -71,6 +71,10 @@ pointed to. T must meet the smart pointer weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws template<typename T, typename U> weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r); + template<typename T, typename U> + weak_ptr<T> shared_polymorphic_cast(weak_ptr<U> const & r); + template<typename T, typename U> + weak_ptr<T> shared_polymorphic_downcast(weak_ptr<U> const & r); // never throws } @@ -192,19 +196,35 @@ Provided as an aid to generic programming.

shared_static_cast

template<typename T, typename U>
-  weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws
+ weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws

Perform a static_cast on the stored pointer, returning another weak_ptr. The resulting smart pointer will share its use count with the original pointer.

shared_dynamic_cast

template<typename T, typename U>
-  weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);
+ weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);

Perform a dynamic_cast on the stored pointer, returning another weak_ptr. The resulting smart pointer will share its use count with the original pointer unless the result of the cast is 0. The only exception which may be thrown is std::bad_alloc, which may be thrown during the construction of the new weak_ptr if the result of the cast is 0. If an exception is thrown, the cast has no effect.

+

shared_polymorphic_cast

+
template<typename T, typename U>
+  weak_ptr<T> shared_polymorphic_cast(weak_ptr<U> const & r);
+

Perform a polymorphic_cast on the stored pointer, +returning another weak_ptr. +The resulting smart pointer will share its use count with the original pointer. +The only exception which may be thrown is std::bad_cast, if the pointer type can not be converted. +If an exception is thrown, the cast has no effect.

+ +

shared_polymorphic_downcast

+
template<typename T, typename U>
+  weak_ptr<T> shared_polymorphic_downcast(weak_ptr<U> const & r); // never throws
+

Perform a polymorphic_downcast on the stored pointer, +returning another weak_ptr. +The resulting smart pointer will share its use count with the original pointer.

+

Revised 1 February 2002