Boost logo

Boost-Commit :

From: pdimov_at_[hidden]
Date: 2008-05-03 11:07:59


Author: pdimov
Date: 2008-05-03 11:07:58 EDT (Sat, 03 May 2008)
New Revision: 45068
URL: http://svn.boost.org/trac/boost/changeset/45068

Log:
Fix #1106.
Added:
   trunk/boost/detail/sp_convertible.hpp (contents, props changed)
   trunk/libs/smart_ptr/test/ip_convertible_test.cpp (contents, props changed)
   trunk/libs/smart_ptr/test/sp_convertible_test.cpp (contents, props changed)
   trunk/libs/smart_ptr/test/wp_convertible_test.cpp (contents, props changed)
Text files modified:
   trunk/boost/intrusive_ptr.hpp | 31 ++++++++++++++++++++++++++++---
   trunk/boost/shared_ptr.hpp | 17 +++++++++++++++--
   trunk/boost/weak_ptr.hpp | 22 ++++++++++++++++++++--
   trunk/libs/smart_ptr/test/Jamfile.v2 | 3 +++
   4 files changed, 66 insertions(+), 7 deletions(-)

Added: trunk/boost/detail/sp_convertible.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/detail/sp_convertible.hpp 2008-05-03 11:07:58 EDT (Sat, 03 May 2008)
@@ -0,0 +1,60 @@
+#ifndef BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
+#define BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_convertible.hpp
+//
+// Copyright 2008 Peter Dimov
+//
+// 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
+
+#include <boost/config.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+template< class Y, class T > struct sp_convertible
+{
+ typedef char (&yes) [1];
+ typedef char (&no) [2];
+
+ static yes f( T* );
+ static no f( ... );
+
+ enum _vt { value = sizeof( f( (Y*)0 ) ) == sizeof(yes) };
+};
+
+struct sp_empty
+{
+};
+
+template< bool > struct sp_enable_if_convertible_impl;
+
+template<> struct sp_enable_if_convertible_impl<true>
+{
+ typedef sp_empty type;
+};
+
+template<> struct sp_enable_if_convertible_impl<false>
+{
+};
+
+template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value >
+{
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED

Modified: trunk/boost/intrusive_ptr.hpp
==============================================================================
--- trunk/boost/intrusive_ptr.hpp (original)
+++ trunk/boost/intrusive_ptr.hpp 2008-05-03 11:07:58 EDT (Sat, 03 May 2008)
@@ -23,8 +23,19 @@
 #include <boost/assert.hpp>
 #include <boost/detail/workaround.hpp>
 
+#if !defined( BOOST_NO_SFINAE )
+#include <boost/detail/sp_convertible.hpp>
+#endif
+
 #include <functional> // for std::less
+
+#if !defined(BOOST_NO_IOSTREAM)
+#if !defined(BOOST_NO_IOSFWD)
 #include <iosfwd> // for std::basic_ostream
+#else
+#include <ostream>
+#endif
+#endif
 
 
 namespace boost
@@ -66,9 +77,19 @@
 
 #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
 
- template<class U> intrusive_ptr(intrusive_ptr<U> const & rhs): p_(rhs.get())
+ template<class U>
+#if !defined( BOOST_NO_SFINAE )
+
+ intrusive_ptr( intrusive_ptr<U> const & rhs, typename detail::sp_enable_if_convertible<U,T>::type = detail::sp_empty() )
+
+#else
+
+ intrusive_ptr( intrusive_ptr<U> const & rhs )
+
+#endif
+ : p_( rhs.get() )
     {
- if(p_ != 0) intrusive_ptr_add_ref(p_);
+ if( p_ != 0 ) intrusive_ptr_add_ref( p_ );
     }
 
 #endif
@@ -246,7 +267,9 @@
 
 // operator<<
 
-#if defined(__GNUC__) && (__GNUC__ < 3)
+#if !defined(BOOST_NO_IOSTREAM)
+
+#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
 
 template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
 {
@@ -275,6 +298,8 @@
 
 #endif // __GNUC__ < 3
 
+#endif // !defined(BOOST_NO_IOSTREAM)
+
 } // namespace boost
 
 #ifdef BOOST_MSVC

Modified: trunk/boost/shared_ptr.hpp
==============================================================================
--- trunk/boost/shared_ptr.hpp (original)
+++ trunk/boost/shared_ptr.hpp 2008-05-03 11:07:58 EDT (Sat, 03 May 2008)
@@ -32,6 +32,10 @@
 #include <boost/detail/shared_count.hpp>
 #include <boost/detail/workaround.hpp>
 
+#if !defined( BOOST_NO_SFINAE )
+#include <boost/detail/sp_convertible.hpp>
+#endif
+
 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
 #include <boost/detail/spinlock_pool.hpp>
 #include <boost/memory_order.hpp>
@@ -224,11 +228,20 @@
     }
 
     template<class Y>
- shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
+#if !defined( BOOST_NO_SFINAE )
+
+ shared_ptr( shared_ptr<Y> const & r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
+
+#else
+
+ shared_ptr( shared_ptr<Y> const & r )
+
+#endif
+ : px( r.px ), pn( r.pn ) // never throws
     {
     }
 
- shared_ptr(detail::shared_count const & c, T * p): px(p), pn(c) // never throws
+ shared_ptr( detail::shared_count const & c, T * p ): px( p ), pn( c ) // never throws
     {
     }
 

Modified: trunk/boost/weak_ptr.hpp
==============================================================================
--- trunk/boost/weak_ptr.hpp (original)
+++ trunk/boost/weak_ptr.hpp 2008-05-03 11:07:58 EDT (Sat, 03 May 2008)
@@ -61,13 +61,31 @@
 //
 
     template<class Y>
- weak_ptr(weak_ptr<Y> const & r): pn(r.pn) // never throws
+#if !defined( BOOST_NO_SFINAE )
+
+ weak_ptr( weak_ptr<Y> const & r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
+
+#else
+
+ weak_ptr( weak_ptr<Y> const & r )
+
+#endif
+ : pn(r.pn) // never throws
     {
         px = r.lock().get();
     }
 
     template<class Y>
- weak_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
+#if !defined( BOOST_NO_SFINAE )
+
+ weak_ptr( shared_ptr<Y> const & r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
+
+#else
+
+ weak_ptr( shared_ptr<Y> const & r )
+
+#endif
+ : px( r.px ), pn( r.pn ) // never throws
     {
     }
 

Modified: trunk/libs/smart_ptr/test/Jamfile.v2
==============================================================================
--- trunk/libs/smart_ptr/test/Jamfile.v2 (original)
+++ trunk/libs/smart_ptr/test/Jamfile.v2 2008-05-03 11:07:58 EDT (Sat, 03 May 2008)
@@ -46,5 +46,8 @@
           [ run sp_accept_owner_test.cpp ]
           [ run sp_atomic_test.cpp ]
           [ run make_shared_test.cpp ]
+ [ run sp_convertible_test.cpp ]
+ [ run wp_convertible_test.cpp ]
+ [ run ip_convertible_test.cpp ]
         ;
 }

Added: trunk/libs/smart_ptr/test/ip_convertible_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/ip_convertible_test.cpp 2008-05-03 11:07:58 EDT (Sat, 03 May 2008)
@@ -0,0 +1,54 @@
+#include <boost/config.hpp>
+
+// wp_convertible_test.cpp
+//
+// Copyright (c) 2008 Peter Dimov
+//
+// 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+//
+
+struct W
+{
+};
+
+void intrusive_ptr_add_ref( W* )
+{
+}
+
+void intrusive_ptr_release( W* )
+{
+}
+
+struct X: public virtual W
+{
+};
+
+struct Y: public virtual W
+{
+};
+
+struct Z: public X
+{
+};
+
+int f( boost::intrusive_ptr<X> )
+{
+ return 1;
+}
+
+int f( boost::intrusive_ptr<Y> )
+{
+ return 2;
+}
+
+int main()
+{
+ BOOST_TEST( 1 == f( boost::intrusive_ptr<Z>() ) );
+ return boost::report_errors();
+}

Added: trunk/libs/smart_ptr/test/sp_convertible_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_convertible_test.cpp 2008-05-03 11:07:58 EDT (Sat, 03 May 2008)
@@ -0,0 +1,66 @@
+#include <boost/config.hpp>
+
+// sp_convertible_test.cpp
+//
+// Copyright (c) 2008 Peter Dimov
+//
+// 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/shared_ptr.hpp>
+
+//
+
+class incomplete;
+
+struct X
+{
+};
+
+struct Y
+{
+};
+
+struct Z: public X
+{
+};
+
+int f( boost::shared_ptr<void const> )
+{
+ return 1;
+}
+
+int f( boost::shared_ptr<int> )
+{
+ return 2;
+}
+
+int f( boost::shared_ptr<incomplete> )
+{
+ return 3;
+}
+
+int g( boost::shared_ptr<X> )
+{
+ return 4;
+}
+
+int g( boost::shared_ptr<Y> )
+{
+ return 5;
+}
+
+int g( boost::shared_ptr<incomplete> )
+{
+ return 6;
+}
+
+int main()
+{
+ BOOST_TEST( 1 == f( boost::shared_ptr<double>() ) );
+ BOOST_TEST( 4 == g( boost::shared_ptr<Z>() ) );
+
+ return boost::report_errors();
+}

Added: trunk/libs/smart_ptr/test/wp_convertible_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/wp_convertible_test.cpp 2008-05-03 11:07:58 EDT (Sat, 03 May 2008)
@@ -0,0 +1,68 @@
+#include <boost/config.hpp>
+
+// wp_convertible_test.cpp
+//
+// Copyright (c) 2008 Peter Dimov
+//
+// 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/weak_ptr.hpp>
+
+//
+
+class incomplete;
+
+struct X
+{
+};
+
+struct Y
+{
+};
+
+struct Z: public X
+{
+};
+
+int f( boost::weak_ptr<void const> )
+{
+ return 1;
+}
+
+int f( boost::weak_ptr<int> )
+{
+ return 2;
+}
+
+int f( boost::weak_ptr<incomplete> )
+{
+ return 3;
+}
+
+int g( boost::weak_ptr<X> )
+{
+ return 4;
+}
+
+int g( boost::weak_ptr<Y> )
+{
+ return 5;
+}
+
+int g( boost::weak_ptr<incomplete> )
+{
+ return 6;
+}
+
+int main()
+{
+ BOOST_TEST( 1 == f( boost::weak_ptr<double>() ) );
+ BOOST_TEST( 1 == f( boost::shared_ptr<double>() ) );
+ BOOST_TEST( 4 == g( boost::weak_ptr<Z>() ) );
+ BOOST_TEST( 4 == g( boost::shared_ptr<Z>() ) );
+
+ return boost::report_errors();
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk