diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 24af067..06e43fb 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -220,6 +220,11 @@ template intrusive_ptr static_pointer_cast(intrusive_ptr return static_cast(p.get()); } +template intrusive_ptr const_pointer_cast(intrusive_ptr const & p) +{ + return const_cast(p.get()); +} + template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) { return dynamic_cast(p.get()); diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index d33eb77..6663cde 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -48,6 +48,7 @@ namespace detail { struct static_cast_tag {}; +struct const_cast_tag {}; struct dynamic_cast_tag {}; struct polymorphic_cast_tag {}; @@ -68,6 +69,16 @@ template<> struct shared_ptr_traits typedef void reference; }; +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + #endif // enable_shared_from_this support @@ -158,6 +169,11 @@ public: { } + template + shared_ptr(shared_ptr const & r, detail::const_cast_tag): px(const_cast(r.px)), pn(r.pn) + { + } + template shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { @@ -351,6 +367,11 @@ template shared_ptr static_pointer_cast(shared_ptr const return shared_ptr(r, detail::static_cast_tag()); } +template shared_ptr const_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::const_cast_tag()); +} + template shared_ptr dynamic_pointer_cast(shared_ptr const & r) { return shared_ptr(r, detail::dynamic_cast_tag()); diff --git a/intrusive_ptr.html b/intrusive_ptr.html index 22bbc0c..66c1401 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -100,6 +100,9 @@ template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws + template<class T, class U> + intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r); // never throws + template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r); // never throws @@ -250,6 +253,13 @@ intrusive_ptr & operator=(T * r);

Returns: intrusive_ptr<T>(static_cast<T*>(r.get())).

Throws: nothing.

+

const_pointer_cast

+
template<class T, class U>
+  intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r); // never throws
+
+

Returns: intrusive_ptr<T>(const_cast<T*>(r.get())).

+

Throws: nothing.

+

dynamic_pointer_cast

template<class T, class U>
   intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r);
diff --git a/shared_ptr.htm b/shared_ptr.htm index 809ceb3..196b777 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -142,6 +142,9 @@ void bad() template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws + template<class T, class U> + shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws + template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws @@ -473,6 +476,21 @@ q = p;

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

+

const_pointer_cast

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

Requires: The expression const_cast<T*>(r.get()) + must be well-formed.

+

Returns: If r is empty, an empty shared_ptr<T>; + otherwise, a shared_ptr<T> object that stores a copy of + const_cast<T*>(r.get()) and shares ownership with r.

+

Throws: nothing.

+

Notes: the seemingly equivalent expression

+

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

+

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

+

dynamic_pointer_cast

template<class T, class U>
   shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);
diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index 95e34d3..9e3bf10 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -2375,6 +2375,57 @@ void test() } // namespace n_static_cast +namespace n_const_cast +{ + +struct X; + +void test() +{ + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px2.get() == 0); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px2.get() == 0); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px2.get() == 0); + } + + { + boost::shared_ptr px(new int); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(px2.use_count() == 2); + } + + { + boost::shared_ptr px(new int); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(px2.use_count() == 2); + } +} + +} // namespace n_const_cast + namespace n_dynamic_cast { @@ -3141,6 +3192,7 @@ int main() n_swap::test(); n_comparison::test(); n_static_cast::test(); + n_const_cast::test(); n_dynamic_cast::test(); n_map::test();