Prepare shared_ptr for array support
authorJonathan Wakely <jwakely@redhat.com>
Thu, 20 Oct 2016 12:07:45 +0000 (13:07 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 20 Oct 2016 12:07:45 +0000 (13:07 +0100)
* include/backward/auto_ptr.h (__shared_ptr(auto_ptr&&))
(shared_ptr(auto_ptr&&)): Adjust template parameter lists.
* include/bits/shared_ptr.h (__sp_compatible_with)
(__sp_is_constructible): New helper traits for shared_ptr.
(shared_ptr::_Convertible): Replace with _Constructible.
(shared_ptr::_Constructible, shared_ptr::_Assignable): Forward checks
to base class.
(shared_ptr::shared_ptr, shared_ptr::operator=): Constrain template
with _Constructible and _Assignable.
(shared_ptr::shared_ptr(shared_ptr<_Tp1>, _Tp*)): Use element_type
instead of _Tp.
(operator<): Likewise.
(operator>): Define in terms of operator<.
(static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use
element_type instead of _Tp.
(reinterpret_pointer_cast): Define for C++17.
(weak_ptr::_Convertible): Replace with _Constructible.
(weak_ptr::_Constructible, weak_ptr::_Assignable): Forward checks
to base class.
(weak_ptr::weak_ptr, weak_ptr::operator=): Constrain templates
with _Constructible and _Assignable.
* include/bits/shared_ptr_base.h (__shared_ptr::_Convertible): Replace
with _Compatible.
(__shared_ptr::_SafeConv): New constraint for incoming raw pointers.
(__shared_ptr::_Compatible): New constraint for converting from
other types of shared_ptr and weak_ptr.
(__shared_ptr::_Assignable): Define in terms of _Compatible.
(__shared_ptr::_UniqCompatible, __shared_ptr::_UniqAssignable): New
constraints for converting from unique_ptr.
(__shared_ptr::__shared_ptr, __shared_ptr::operator=): Constrain
template with _SaveConf, _Compatible and _Assignable. Remove
__glibcxx_function_requires concept checks. Add static assertion for
deleter expression being well-formed.
(__shared_ptr::__shared_ptr(__shared_ptr<_Tp1>, _Tp*))
(__shared_ptr::operator*, __shared_ptr::operator->)
(__shared_ptr::get, __shared_ptr::_M_ptr): Use element_type instead
of _Tp.
(operator<): Likewise.
(operator>): Define in terms of operator<.
(static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use
element_type instead of _Tp.
(reinterpret_pointer_cast): Define for C++17.
(weak_ptr::_Convertible): Replace with _Compatible.
(weak_ptr::_Compatible, weak_ptr::_Assignable): New constraints for
conversions from other types of weak_ptr and shared_ptr.
(__weak_ptr::__weak_ptr, __weak_ptr::operator=): Constrain templates
with _Constructible and _Assignable.
(__weak_ptr::_M_ptr): Use element_type instead of _Tp.
* testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc: Adjust
dg-error pattern.
* testsuite/20_util/shared_ptr/cons/auto_ptr.cc: Test conversions.
* testsuite/20_util/shared_ptr/cons/unique_ptr.cc: Likewise.
* testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.
* testsuite/20_util/shared_ptr/casts/reinterpret.cc: New test.

From-SVN: r241373

libstdc++-v3/ChangeLog
libstdc++-v3/include/backward/auto_ptr.h
libstdc++-v3/include/bits/shared_ptr.h
libstdc++-v3/include/bits/shared_ptr_base.h
libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc
libstdc++-v3/testsuite/20_util/shared_ptr/casts/reinterpret.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr.cc
libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc
libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc

index 378e9fad1457bec7dd26e8e0fba91bb2a6968712..6f47e0d2b620131c5f5baa9bcf12a097eb0353e0 100644 (file)
@@ -1,3 +1,60 @@
+2016-10-20  Jonathan Wakely  <jwakely@redhat.com>
+
+       * include/backward/auto_ptr.h (__shared_ptr(auto_ptr&&))
+       (shared_ptr(auto_ptr&&)): Adjust template parameter lists.
+       * include/bits/shared_ptr.h (__sp_compatible_with)
+       (__sp_is_constructible): New helper traits for shared_ptr.
+       (shared_ptr::_Convertible): Replace with _Constructible.
+       (shared_ptr::_Constructible, shared_ptr::_Assignable): Forward checks
+       to base class.
+       (shared_ptr::shared_ptr, shared_ptr::operator=): Constrain template
+       with _Constructible and _Assignable.
+       (shared_ptr::shared_ptr(shared_ptr<_Tp1>, _Tp*)): Use element_type
+       instead of _Tp.
+       (operator<): Likewise.
+       (operator>): Define in terms of operator<.
+       (static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use
+       element_type instead of _Tp.
+       (reinterpret_pointer_cast): Define for C++17.
+       (weak_ptr::_Convertible): Replace with _Constructible.
+       (weak_ptr::_Constructible, weak_ptr::_Assignable): Forward checks
+       to base class.
+       (weak_ptr::weak_ptr, weak_ptr::operator=): Constrain templates
+       with _Constructible and _Assignable.
+       * include/bits/shared_ptr_base.h (__shared_ptr::_Convertible): Replace
+       with _Compatible.
+       (__shared_ptr::_SafeConv): New constraint for incoming raw pointers.
+       (__shared_ptr::_Compatible): New constraint for converting from
+       other types of shared_ptr and weak_ptr.
+       (__shared_ptr::_Assignable): Define in terms of _Compatible.
+       (__shared_ptr::_UniqCompatible, __shared_ptr::_UniqAssignable): New
+       constraints for converting from unique_ptr.
+       (__shared_ptr::__shared_ptr, __shared_ptr::operator=): Constrain
+       template with _SaveConf, _Compatible and _Assignable. Remove
+       __glibcxx_function_requires concept checks. Add static assertion for
+       deleter expression being well-formed.
+       (__shared_ptr::__shared_ptr(__shared_ptr<_Tp1>, _Tp*))
+       (__shared_ptr::operator*, __shared_ptr::operator->)
+       (__shared_ptr::get, __shared_ptr::_M_ptr): Use element_type instead
+       of _Tp.
+       (operator<): Likewise.
+       (operator>): Define in terms of operator<.
+       (static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use
+       element_type instead of _Tp.
+       (reinterpret_pointer_cast): Define for C++17.
+       (weak_ptr::_Convertible): Replace with _Compatible.
+       (weak_ptr::_Compatible, weak_ptr::_Assignable): New constraints for
+       conversions from other types of weak_ptr and shared_ptr.
+       (__weak_ptr::__weak_ptr, __weak_ptr::operator=): Constrain templates
+       with _Constructible and _Assignable.
+       (__weak_ptr::_M_ptr): Use element_type instead of _Tp.
+       * testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc: Adjust
+       dg-error pattern.
+       * testsuite/20_util/shared_ptr/cons/auto_ptr.cc: Test conversions.
+       * testsuite/20_util/shared_ptr/cons/unique_ptr.cc: Likewise.
+       * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.
+       * testsuite/20_util/shared_ptr/casts/reinterpret.cc: New test.
+
 2016-10-20  Ville Voutilainen  <ville.voutilainen@gmail.com>
 
        Do the operator= SFINAE in the return type for optional,
index 94911c87981ecd71ea95e5f5236769025b4d0a25..855b6f90dea215ec0698162ed9e829f327ec9d1d 100644 (file)
@@ -302,7 +302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { __r.release(); }
 
   template<typename _Tp, _Lock_policy _Lp>
-  template<typename _Tp1>
+  template<typename _Tp1, typename>
     inline
     __shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Tp1>&& __r)
     : _M_ptr(__r.get()), _M_refcount()
@@ -315,7 +315,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _Tp>
-  template<typename _Tp1>
+  template<typename _Tp1, typename>
     inline
     shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Tp1>&& __r)
     : __shared_ptr<_Tp>(std::move(__r)) { }
index 9b9261c04e45b000329c4958844ea05ce4a2de4e..9f7a40c5e1ed17b0b6a5fb0fd660c26a9e82552e 100644 (file)
@@ -92,16 +92,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     class shared_ptr : public __shared_ptr<_Tp>
     {
-      template<typename _Ptr>
-       using _Convertible = typename
-         enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+      template<typename... _Args>
+       using _Constructible = typename enable_if<
+         is_constructible<__shared_ptr<_Tp>, _Args...>::value
+       >::type;
 
-      template<typename _Ptr>
-       using _Assignable = typename
-         enable_if<is_convertible<_Ptr, _Tp*>::value, shared_ptr&>::type;
+      template<typename _Arg>
+       using _Assignable = typename enable_if<
+         is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
+       >::type;
 
     public:
 
+      using element_type = typename __shared_ptr<_Tp>::element_type;
+
 #if __cplusplus > 201402L
 # define __cpp_lib_shared_ptr_weak_type 201606
       using weak_type = weak_ptr<_Tp>;
@@ -110,8 +114,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  @brief  Construct an empty %shared_ptr.
        *  @post   use_count()==0 && get()==0
        */
-      constexpr shared_ptr() noexcept
-      : __shared_ptr<_Tp>() { }
+      constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
 
       shared_ptr(const shared_ptr&) noexcept = default;
 
@@ -121,9 +124,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  @post   use_count() == 1 && get() == __p
        *  @throw  std::bad_alloc, in which case @c delete @a __p is called.
        */
-      template<typename _Tp1>
-       explicit shared_ptr(_Tp1* __p)
-        : __shared_ptr<_Tp>(__p) { }
+      template<typename _Yp, typename = _Constructible<_Yp*>>
+       explicit
+       shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
 
       /**
        *  @brief  Construct a %shared_ptr that owns the pointer @a __p
@@ -138,8 +141,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *
        *  __shared_ptr will release __p by calling __d(__p)
        */
-      template<typename _Tp1, typename _Deleter>
-       shared_ptr(_Tp1* __p, _Deleter __d)
+      template<typename _Yp, typename _Deleter,
+              typename = _Constructible<_Yp*, _Deleter>>
+       shared_ptr(_Yp* __p, _Deleter __d)
         : __shared_ptr<_Tp>(__p, __d) { }
 
       /**
@@ -174,8 +178,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *
        *  __shared_ptr will release __p by calling __d(__p)
        */
-      template<typename _Tp1, typename _Deleter, typename _Alloc>
-       shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
+      template<typename _Yp, typename _Deleter, typename _Alloc,
+              typename = _Constructible<_Yp*, _Deleter, _Alloc>>
+       shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
        : __shared_ptr<_Tp>(__p, __d, std::move(__a)) { }
 
       /**
@@ -215,8 +220,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        * assert(pii.use_count() == 2);
        * @endcode
        */
-      template<typename _Tp1>
-       shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) noexcept
+      template<typename _Yp>
+       shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
        : __shared_ptr<_Tp>(__r, __p) { }
 
       /**
@@ -226,8 +231,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  @param  __r  A %shared_ptr.
        *  @post   get() == __r.get() && use_count() == __r.use_count()
        */
-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
-       shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
+      template<typename _Yp,
+              typename = _Constructible<const shared_ptr<_Yp>&>>
+       shared_ptr(const shared_ptr<_Yp>& __r) noexcept
         : __shared_ptr<_Tp>(__r) { }
 
       /**
@@ -243,8 +249,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  @param  __r  A %shared_ptr rvalue.
        *  @post   *this contains the old value of @a __r, @a __r is empty.
        */
-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
-       shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
+      template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
+       shared_ptr(shared_ptr<_Yp>&& __r) noexcept
        : __shared_ptr<_Tp>(std::move(__r)) { }
 
       /**
@@ -255,20 +261,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  @throw  bad_weak_ptr when __r.expired(),
        *          in which case the constructor has no effect.
        */
-      template<typename _Tp1>
-       explicit shared_ptr(const weak_ptr<_Tp1>& __r)
+      template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
+       explicit shared_ptr(const weak_ptr<_Yp>& __r)
        : __shared_ptr<_Tp>(__r) { }
 
 #if _GLIBCXX_USE_DEPRECATED
-      template<typename _Tp1>
-       shared_ptr(std::auto_ptr<_Tp1>&& __r);
+      template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
+       shared_ptr(auto_ptr<_Yp>&& __r);
 #endif
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 2399. shared_ptr's constructor from unique_ptr should be constrained
-      template<typename _Tp1, typename _Del, typename
-              = _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
-       shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
+      template<typename _Yp, typename _Del,
+              typename = _Constructible<unique_ptr<_Yp, _Del>>>
+       shared_ptr(unique_ptr<_Yp, _Del>&& __r)
        : __shared_ptr<_Tp>(std::move(__r)) { }
 
       /**
@@ -279,18 +285,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       shared_ptr& operator=(const shared_ptr&) noexcept = default;
 
-      template<typename _Tp1>
-       _Assignable<_Tp1*>
-       operator=(const shared_ptr<_Tp1>& __r) noexcept
+      template<typename _Yp>
+       _Assignable<const shared_ptr<_Yp>&>
+       operator=(const shared_ptr<_Yp>& __r) noexcept
        {
          this->__shared_ptr<_Tp>::operator=(__r);
          return *this;
        }
 
 #if _GLIBCXX_USE_DEPRECATED
-      template<typename _Tp1>
-       shared_ptr&
-       operator=(std::auto_ptr<_Tp1>&& __r)
+      template<typename _Yp>
+       _Assignable<auto_ptr<_Yp>>
+       operator=(auto_ptr<_Yp>&& __r)
        {
          this->__shared_ptr<_Tp>::operator=(std::move(__r));
          return *this;
@@ -304,17 +310,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return *this;
       }
 
-      template<class _Tp1>
-       _Assignable<_Tp1*>
-       operator=(shared_ptr<_Tp1>&& __r) noexcept
+      template<class _Yp>
+       _Assignable<shared_ptr<_Yp>>
+       operator=(shared_ptr<_Yp>&& __r) noexcept
        {
          this->__shared_ptr<_Tp>::operator=(std::move(__r));
          return *this;
        }
 
-      template<typename _Tp1, typename _Del>
-       _Assignable<typename unique_ptr<_Tp1, _Del>::pointer>
-       operator=(std::unique_ptr<_Tp1, _Del>&& __r)
+      template<typename _Yp, typename _Del>
+       _Assignable<unique_ptr<_Yp, _Del>>
+       operator=(unique_ptr<_Yp, _Del>&& __r)
        {
          this->__shared_ptr<_Tp>::operator=(std::move(__r));
          return *this;
@@ -328,8 +334,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
        { }
 
-      template<typename _Tp1, typename _Alloc, typename... _Args>
-       friend shared_ptr<_Tp1>
+      template<typename _Yp, typename _Alloc, typename... _Args>
+       friend shared_ptr<_Yp>
        allocate_shared(const _Alloc& __a, _Args&&... __args);
 
       // This constructor is non-standard, it is used by weak_ptr::lock().
@@ -340,10 +346,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     };
 
   // 20.7.2.2.7 shared_ptr comparisons
-  template<typename _Tp1, typename _Tp2>
+  template<typename _Tp, typename _Up>
     inline bool
-    operator==(const shared_ptr<_Tp1>& __a,
-              const shared_ptr<_Tp2>& __b) noexcept
+    operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
     { return __a.get() == __b.get(); }
 
   template<typename _Tp>
@@ -356,10 +361,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
     { return !__a; }
 
-  template<typename _Tp1, typename _Tp2>
+  template<typename _Tp, typename _Up>
     inline bool
-    operator!=(const shared_ptr<_Tp1>& __a,
-              const shared_ptr<_Tp2>& __b) noexcept
+    operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
     { return __a.get() != __b.get(); }
 
   template<typename _Tp>
@@ -372,29 +376,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
     { return (bool)__a; }
 
-  template<typename _Tp1, typename _Tp2>
+  template<typename _Tp, typename _Up>
     inline bool
-    operator<(const shared_ptr<_Tp1>& __a,
-             const shared_ptr<_Tp2>& __b) noexcept
+    operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
     {
-      typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT;
-      return std::less<_CT>()(__a.get(), __b.get());
+      using _Tp_elt = typename shared_ptr<_Tp>::element_type;
+      using _Up_elt = typename shared_ptr<_Up>::element_type;
+      using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
+      return less<_Vp>()(__a.get(), __b.get());
     }
 
   template<typename _Tp>
     inline bool
     operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
-    { return std::less<_Tp*>()(__a.get(), nullptr); }
+    {
+      using _Tp_elt = typename shared_ptr<_Tp>::element_type;
+      return less<_Tp_elt*>()(__a.get(), nullptr);
+    }
 
   template<typename _Tp>
     inline bool
     operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
-    { return std::less<_Tp*>()(nullptr, __a.get()); }
+    {
+      using _Tp_elt = typename shared_ptr<_Tp>::element_type;
+      return less<_Tp_elt*>()(nullptr, __a.get());
+    }
 
-  template<typename _Tp1, typename _Tp2>
+  template<typename _Tp, typename _Up>
     inline bool
-    operator<=(const shared_ptr<_Tp1>& __a,
-              const shared_ptr<_Tp2>& __b) noexcept
+    operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
     { return !(__b < __a); }
 
   template<typename _Tp>
@@ -407,26 +417,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
     { return !(__a < nullptr); }
 
-  template<typename _Tp1, typename _Tp2>
+  template<typename _Tp, typename _Up>
     inline bool
-    operator>(const shared_ptr<_Tp1>& __a,
-             const shared_ptr<_Tp2>& __b) noexcept
+    operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
     { return (__b < __a); }
 
   template<typename _Tp>
     inline bool
     operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
-    { return std::less<_Tp*>()(nullptr, __a.get()); }
+    { return nullptr < __a; }
 
   template<typename _Tp>
     inline bool
     operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
-    { return std::less<_Tp*>()(__a.get(), nullptr); }
+    { return __a < nullptr; }
 
-  template<typename _Tp1, typename _Tp2>
+  template<typename _Tp, typename _Up>
     inline bool
-    operator>=(const shared_ptr<_Tp1>& __a,
-              const shared_ptr<_Tp2>& __b) noexcept
+    operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
     { return !(__a < __b); }
 
   template<typename _Tp>
@@ -450,25 +458,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { __a.swap(__b); }
 
   // 20.7.2.2.9 shared_ptr casts.
-  template<typename _Tp, typename _Tp1>
+  template<typename _Tp, typename _Up>
     inline shared_ptr<_Tp>
-    static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
-    { return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get())); }
+    static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
+    {
+      using _Sp = shared_ptr<_Tp>;
+      return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
+    }
 
-  template<typename _Tp, typename _Tp1>
+  template<typename _Tp, typename _Up>
     inline shared_ptr<_Tp>
-    const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
-    { return shared_ptr<_Tp>(__r, const_cast<_Tp*>(__r.get())); }
+    const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
+    {
+      using _Sp = shared_ptr<_Tp>;
+      return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
+    }
 
-  template<typename _Tp, typename _Tp1>
+  template<typename _Tp, typename _Up>
     inline shared_ptr<_Tp>
-    dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
+    dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
     {
-      if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
-       return shared_ptr<_Tp>(__r, __p);
-      return shared_ptr<_Tp>();
+      using _Sp = shared_ptr<_Tp>;
+      if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
+       return _Sp(__r, __p);
+      return _Sp();
     }
 
+#if __cplusplus > 201402L
+  template<typename _Tp, typename _Up>
+    inline shared_ptr<_Tp>
+    reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept
+    {
+      using _Sp = shared_ptr<_Tp>;
+      return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
+    }
+#endif
 
   /**
    *  @brief  A smart pointer with weak semantics.
@@ -478,43 +502,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     class weak_ptr : public __weak_ptr<_Tp>
     {
-      template<typename _Ptr>
-       using _Convertible
-         = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+      template<typename _Arg>
+       using _Constructible = typename enable_if<
+         is_constructible<__weak_ptr<_Tp>, _Arg>::value
+       >::type;
+
+      template<typename _Arg>
+       using _Assignable = typename enable_if<
+         is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&
+       >::type;
 
     public:
       constexpr weak_ptr() noexcept = default;
 
-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
-       weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
+      template<typename _Yp,
+              typename = _Constructible<const shared_ptr<_Yp>&>>
+       weak_ptr(const shared_ptr<_Yp>& __r) noexcept
        : __weak_ptr<_Tp>(__r) { }
 
       weak_ptr(const weak_ptr&) noexcept = default;
 
-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
-       weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
+      template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
+       weak_ptr(const weak_ptr<_Yp>& __r) noexcept
        : __weak_ptr<_Tp>(__r) { }
 
       weak_ptr(weak_ptr&&) noexcept = default;
 
-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
-       weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
+      template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
+       weak_ptr(weak_ptr<_Yp>&& __r) noexcept
        : __weak_ptr<_Tp>(std::move(__r)) { }
 
       weak_ptr&
       operator=(const weak_ptr& __r) noexcept = default;
 
-      template<typename _Tp1>
-       weak_ptr&
-       operator=(const weak_ptr<_Tp1>& __r) noexcept
+      template<typename _Yp>
+       _Assignable<const weak_ptr<_Yp>&>
+       operator=(const weak_ptr<_Yp>& __r) noexcept
        {
          this->__weak_ptr<_Tp>::operator=(__r);
          return *this;
        }
 
-      template<typename _Tp1>
-       weak_ptr&
-       operator=(const shared_ptr<_Tp1>& __r) noexcept
+      template<typename _Yp>
+       _Assignable<const shared_ptr<_Yp>&>
+       operator=(const shared_ptr<_Yp>& __r) noexcept
        {
          this->__weak_ptr<_Tp>::operator=(__r);
          return *this;
@@ -523,9 +554,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       weak_ptr&
       operator=(weak_ptr&& __r) noexcept = default;
 
-      template<typename _Tp1>
-       weak_ptr&
-       operator=(weak_ptr<_Tp1>&& __r) noexcept
+      template<typename _Yp>
+       _Assignable<weak_ptr<_Yp>>
+       operator=(weak_ptr<_Yp>&& __r) noexcept
        {
          this->__weak_ptr<_Tp>::operator=(std::move(__r));
          return *this;
index c0686ad95da4065304ea13a50bd17358b11cf765..c74c92ae73069ec2992bebd51e32507053d319d8 100644 (file)
@@ -847,19 +847,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          _M_pi = nullptr;
     }
 
+  // Helper traits for shared_ptr
+
+  template<typename _Yp_ptr, typename _Tp_ptr>
+    struct __sp_compatible_with
+    : false_type
+    { };
+
+  template<typename _Yp, typename _Tp>
+    struct __sp_compatible_with<_Yp*, _Tp*>
+    : is_convertible<_Yp*, _Tp*>::type
+    { };
+
   template<typename _Tp, _Lock_policy _Lp>
     class __shared_ptr
     {
-      template<typename _Ptr>
-       using _Convertible
-         = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+    public:
+      using element_type = _Tp;
 
-      template<typename _Ptr>
-       using _Assignable = typename
-         enable_if<is_convertible<_Ptr, _Tp*>::value, __shared_ptr&>::type;
+    private:
+      // Trait to check if shared_ptr<T> can be constructed from Y*.
+      template<typename _Tp1, typename _Yp>
+       using __sp_is_constructible = is_convertible<_Yp*, _Tp1*>;
+
+      // Constraint for taking ownership of a pointer of type _Yp*:
+      template<typename _Yp>
+       using _SafeConv
+         = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;
+
+      // Constraint for construction from shared_ptr and weak_ptr:
+      template<typename _Yp, typename _Res = void>
+       using _Compatible = typename
+         enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
+
+      // Constraint for assignment from shared_ptr and weak_ptr:
+      template<typename _Yp>
+       using _Assignable = _Compatible<_Yp, __shared_ptr&>;
+
+      // Constraint for construction from unique_ptr:
+      template<typename _Yp, typename _Del, typename _Res = void,
+              typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>
+       using _UniqCompatible = typename enable_if<
+         is_convertible<_Ptr, element_type*>::value
+         , _Res>::type;
+
+      // Constraint for assignment from unique_ptr:
+      template<typename _Yp, typename _Del>
+       using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;
 
     public:
-      typedef _Tp   element_type;
 
 #if __cplusplus > 201402L
       using weak_type = __weak_ptr<_Tp, _Lp>;
@@ -869,31 +905,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_ptr(0), _M_refcount()
       { }
 
-      template<typename _Tp1>
-       explicit __shared_ptr(_Tp1* __p)
-        : _M_ptr(__p), _M_refcount(__p)
+      template<typename _Yp, typename = _SafeConv<_Yp>>
+       explicit
+       __shared_ptr(_Yp* __p)
+       : _M_ptr(__p), _M_refcount(__p)
        {
-         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
-         static_assert( !is_void<_Tp1>::value, "incomplete type" );
-         static_assert( sizeof(_Tp1) > 0, "incomplete type" );
+         static_assert( !is_void<_Yp>::value, "incomplete type" );
+         static_assert( sizeof(_Yp) > 0, "incomplete type" );
          _M_enable_shared_from_this_with(__p);
        }
 
-      template<typename _Tp1, typename _Deleter>
-       __shared_ptr(_Tp1* __p, _Deleter __d)
+      template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
+       __shared_ptr(_Yp* __p, _Deleter __d)
        : _M_ptr(__p), _M_refcount(__p, __d)
        {
-         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
-         // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
+         static_assert(__is_callable<_Deleter(_Yp*)>::value,
+             "deleter expression d(p) is well-formed");
          _M_enable_shared_from_this_with(__p);
        }
 
-      template<typename _Tp1, typename _Deleter, typename _Alloc>
-       __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
+      template<typename _Yp, typename _Deleter, typename _Alloc,
+              typename = _SafeConv<_Yp>>
+       __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
        : _M_ptr(__p), _M_refcount(__p, __d, std::move(__a))
        {
-         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
-         // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
+         static_assert(__is_callable<_Deleter(_Yp*)>::value,
+             "deleter expression d(p) is well-formed");
          _M_enable_shared_from_this_with(__p);
        }
 
@@ -907,8 +944,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        : _M_ptr(0), _M_refcount(__p, __d, std::move(__a))
        { }
 
-      template<typename _Tp1>
-       __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept
+      template<typename _Yp>
+       __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
+                    element_type* __p) noexcept
        : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
        { }
 
@@ -916,8 +954,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
       ~__shared_ptr() = default;
 
-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
-       __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
+      template<typename _Yp, typename = _Compatible<_Yp>>
+       __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
        : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
        { }
 
@@ -928,32 +966,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        __r._M_ptr = 0;
       }
 
-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
-       __shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
+      template<typename _Yp, typename = _Compatible<_Yp>>
+       __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
        : _M_ptr(__r._M_ptr), _M_refcount()
        {
          _M_refcount._M_swap(__r._M_refcount);
          __r._M_ptr = 0;
        }
 
-      template<typename _Tp1>
-       explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
+      template<typename _Yp, typename = _Compatible<_Yp>>
+       explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
        : _M_refcount(__r._M_refcount) // may throw
        {
-         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
-
          // It is now safe to copy __r._M_ptr, as
          // _M_refcount(__r._M_refcount) did not throw.
          _M_ptr = __r._M_ptr;
        }
 
       // If an exception is thrown this constructor has no effect.
-      template<typename _Tp1, typename _Del, typename
-              = _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
-       __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
+      template<typename _Yp, typename _Del,
+              typename = _UniqCompatible<_Yp, _Del>>
+       __shared_ptr(unique_ptr<_Yp, _Del>&& __r)
        : _M_ptr(__r.get()), _M_refcount()
        {
-         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
          auto __raw = _S_raw_ptr(__r.get());
          _M_refcount = __shared_count<_Lp>(std::move(__r));
          _M_enable_shared_from_this_with(__raw);
@@ -961,15 +996,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if _GLIBCXX_USE_DEPRECATED
       // Postcondition: use_count() == 1 and __r.get() == 0
-      template<typename _Tp1>
-       __shared_ptr(std::auto_ptr<_Tp1>&& __r);
+      template<typename _Yp, typename = _Compatible<_Yp>>
+       __shared_ptr(auto_ptr<_Yp>&& __r);
 #endif
 
       constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
 
-      template<typename _Tp1>
-       _Assignable<_Tp1*>
-       operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
+      template<typename _Yp>
+       _Assignable<_Yp>
+       operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
        {
          _M_ptr = __r._M_ptr;
          _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
@@ -977,9 +1012,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
 
 #if _GLIBCXX_USE_DEPRECATED
-      template<typename _Tp1>
-       __shared_ptr&
-       operator=(std::auto_ptr<_Tp1>&& __r)
+      template<typename _Yp>
+       _Assignable<_Yp>
+       operator=(auto_ptr<_Yp>&& __r)
        {
          __shared_ptr(std::move(__r)).swap(*this);
          return *this;
@@ -993,17 +1028,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return *this;
       }
 
-      template<class _Tp1>
-       _Assignable<_Tp1*>
-       operator=(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
+      template<class _Yp>
+       _Assignable<_Yp>
+       operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept
        {
          __shared_ptr(std::move(__r)).swap(*this);
          return *this;
        }
 
-      template<typename _Tp1, typename _Del>
-       _Assignable<typename unique_ptr<_Tp1, _Del>::pointer>
-       operator=(std::unique_ptr<_Tp1, _Del>&& __r)
+      template<typename _Yp, typename _Del>
+       _UniqAssignable<_Yp, _Del>
+       operator=(unique_ptr<_Yp, _Del>&& __r)
        {
          __shared_ptr(std::move(__r)).swap(*this);
          return *this;
@@ -1013,41 +1048,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       reset() noexcept
       { __shared_ptr().swap(*this); }
 
-      template<typename _Tp1>
-       _Convertible<_Tp1*>
-       reset(_Tp1* __p) // _Tp1 must be complete.
+      template<typename _Yp>
+       _SafeConv<_Yp>
+       reset(_Yp* __p) // _Yp must be complete.
        {
          // Catch self-reset errors.
          __glibcxx_assert(__p == 0 || __p != _M_ptr);
          __shared_ptr(__p).swap(*this);
        }
 
-      template<typename _Tp1, typename _Deleter>
-       _Convertible<_Tp1*>
-       reset(_Tp1* __p, _Deleter __d)
+      template<typename _Yp, typename _Deleter>
+       _SafeConv<_Yp>
+       reset(_Yp* __p, _Deleter __d)
        { __shared_ptr(__p, __d).swap(*this); }
 
-      template<typename _Tp1, typename _Deleter, typename _Alloc>
-       _Convertible<_Tp1*>
-        reset(_Tp1* __p, _Deleter __d, _Alloc __a)
+      template<typename _Yp, typename _Deleter, typename _Alloc>
+       _SafeConv<_Yp>
+       reset(_Yp* __p, _Deleter __d, _Alloc __a)
         { __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
 
       // Allow class instantiation when _Tp is [cv-qual] void.
-      typename std::add_lvalue_reference<_Tp>::type
+      typename std::add_lvalue_reference<element_type>::type
       operator*() const noexcept
       {
        __glibcxx_assert(_M_ptr != 0);
        return *_M_ptr;
       }
 
-      _Tp*
+      element_type*
       operator->() const noexcept
       {
        _GLIBCXX_DEBUG_PEDASSERT(_M_ptr != 0);
        return _M_ptr;
       }
 
-      _Tp*
+      element_type*
       get() const noexcept
       { return _M_ptr; }
 
@@ -1192,7 +1227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
        friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
 
-      _Tp*                _M_ptr;         // Contained pointer.
+      element_type*       _M_ptr;         // Contained pointer.
       __shared_count<_Lp>  _M_refcount;    // Reference counter.
     };
 
@@ -1230,24 +1265,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
     { return (bool)__a; }
 
-  template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
+  template<typename _Tp, typename _Up, _Lock_policy _Lp>
     inline bool
-    operator<(const __shared_ptr<_Tp1, _Lp>& __a,
-             const __shared_ptr<_Tp2, _Lp>& __b) noexcept
+    operator<(const __shared_ptr<_Tp, _Lp>& __a,
+             const __shared_ptr<_Up, _Lp>& __b) noexcept
     {
-      typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT;
-      return std::less<_CT>()(__a.get(), __b.get());
+      using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
+      using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type;
+      using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
+      return less<_Vp>()(__a.get(), __b.get());
     }
 
   template<typename _Tp, _Lock_policy _Lp>
     inline bool
     operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
-    { return std::less<_Tp*>()(__a.get(), nullptr); }
+    {
+      using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
+      return less<_Tp_elt*>()(__a.get(), nullptr);
+    }
 
   template<typename _Tp, _Lock_policy _Lp>
     inline bool
     operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
-    { return std::less<_Tp*>()(nullptr, __a.get()); }
+    {
+      using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
+      return less<_Tp_elt*>()(nullptr, __a.get());
+    }
 
   template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
     inline bool
@@ -1274,12 +1317,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, _Lock_policy _Lp>
     inline bool
     operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
-    { return std::less<_Tp*>()(nullptr, __a.get()); }
+    { return nullptr < __a; }
 
   template<typename _Tp, _Lock_policy _Lp>
     inline bool
     operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
-    { return std::less<_Tp*>()(__a.get(), nullptr); }
+    { return __a < nullptr; }
 
   template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
     inline bool
@@ -1329,7 +1372,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
     inline __shared_ptr<_Tp, _Lp>
     static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
-    { return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); }
+    {
+      using _Sp = __shared_ptr<_Tp, _Lp>;
+      return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
+    }
 
   // The seemingly equivalent code:
   // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
@@ -1339,7 +1385,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
     inline __shared_ptr<_Tp, _Lp>
     const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
-    { return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); }
+    {
+      using _Sp = __shared_ptr<_Tp, _Lp>;
+      return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
+    }
 
   // The seemingly equivalent code:
   // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
@@ -1350,21 +1399,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline __shared_ptr<_Tp, _Lp>
     dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
     {
-      if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
-       return __shared_ptr<_Tp, _Lp>(__r, __p);
-      return __shared_ptr<_Tp, _Lp>();
+      using _Sp = __shared_ptr<_Tp, _Lp>;
+      if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
+       return _Sp(__r, __p);
+      return _Sp();
     }
 
+#if __cplusplus > 201402L
+  template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
+    inline __shared_ptr<_Tp, _Lp>
+    reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
+    {
+      using _Sp = __shared_ptr<_Tp, _Lp>;
+      return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
+    }
+#endif
 
   template<typename _Tp, _Lock_policy _Lp>
     class __weak_ptr
     {
-      template<typename _Ptr>
-       using _Convertible
-         = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+      template<typename _Yp, typename _Res = void>
+       using _Compatible = typename
+         enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
+
+      // Constraint for assignment from shared_ptr and weak_ptr:
+      template<typename _Yp>
+       using _Assignable = _Compatible<_Yp, __weak_ptr&>;
 
     public:
-      typedef _Tp element_type;
+      using element_type = _Tp;
 
       constexpr __weak_ptr() noexcept
       : _M_ptr(nullptr), _M_refcount()
@@ -1388,13 +1451,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       //
       // It is not possible to avoid spurious access violations since
       // in multithreaded programs __r._M_ptr may be invalidated at any point.
-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
-       __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
+      template<typename _Yp, typename = _Compatible<_Yp>>
+       __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
        : _M_refcount(__r._M_refcount)
         { _M_ptr = __r.lock().get(); }
 
-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
-       __weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
+      template<typename _Yp, typename = _Compatible<_Yp>>
+       __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
        : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
        { }
 
@@ -1402,26 +1465,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
       { __r._M_ptr = nullptr; }
 
-      template<typename _Tp1, typename = _Convertible<_Tp1*>>
-       __weak_ptr(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
+      template<typename _Yp, typename = _Compatible<_Yp>>
+       __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
        : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
         { __r._M_ptr = nullptr; }
 
       __weak_ptr&
       operator=(const __weak_ptr& __r) noexcept = default;
 
-      template<typename _Tp1>
-       __weak_ptr&
-       operator=(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
+      template<typename _Yp>
+       _Assignable<_Yp>
+       operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
        {
          _M_ptr = __r.lock().get();
          _M_refcount = __r._M_refcount;
          return *this;
        }
 
-      template<typename _Tp1>
-       __weak_ptr&
-       operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
+      template<typename _Yp>
+       _Assignable<_Yp>
+       operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
        {
          _M_ptr = __r._M_ptr;
          _M_refcount = __r._M_refcount;
@@ -1437,9 +1500,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return *this;
       }
 
-      template<typename _Tp1>
-       __weak_ptr&
-       operator=(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
+      template<typename _Yp>
+       _Assignable<_Yp>
+       operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
        {
          _M_ptr = __r.lock().get();
          _M_refcount = std::move(__r._M_refcount);
@@ -1497,7 +1560,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       friend class __enable_shared_from_this<_Tp, _Lp>;
       friend class enable_shared_from_this<_Tp>;
 
-      _Tp*              _M_ptr;         // Contained pointer.
+      element_type*     _M_ptr;         // Contained pointer.
       __weak_count<_Lp>  _M_refcount;    // Reference counter.
     };
 
index 56d818ec10a76aad0624f9544504b4e20d578c10..0558cf4153ff16f67c5bf78f21651e3babbe2239 100644 (file)
@@ -34,7 +34,7 @@ test01()
 {
   std::shared_ptr<A> a;
   std::auto_ptr<B> b;
-  a = std::move(b);                      // { dg-error "here" }
+  a = std::move(b);                      // { dg-error "no match" }
 
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/casts/reinterpret.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/casts/reinterpret.cc
new file mode 100644 (file)
index 0000000..e519f0e
--- /dev/null
@@ -0,0 +1,42 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.11.2.2.9 shared_ptr casts [util.smartptr.shared.cast]
+
+#include <memory>
+#include <testsuite_tr1.h>
+
+struct MyP { virtual ~MyP() { }; };
+struct MyDP : MyP { };
+
+int main()
+{
+  using __gnu_test::check_ret_type;
+  using std::shared_ptr;
+  using std::reinterpret_pointer_cast;
+
+  shared_ptr<double> spd;
+  shared_ptr<const int> spci;
+  shared_ptr<MyP> spa;
+
+  check_ret_type<shared_ptr<void> >(reinterpret_pointer_cast<void>(spd));
+  check_ret_type<shared_ptr<const short> >(reinterpret_pointer_cast<const short>(spci));
+  check_ret_type<shared_ptr<MyDP> >(reinterpret_pointer_cast<MyDP>(spa));
+}
index 7a99490bcacc92729b2d6af7df21752313249c67..52481c122e2ec92c1bb12c4939fc9dec751586b6 100644 (file)
 
 struct A { };
 
+int destroyed = 0;
+struct B : A { ~B() { ++destroyed; } };
+
 // 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const]
 
 // Construction from auto_ptr
-int
+
+template<typename From, typename To>
+constexpr bool constructible()
+{
+  using namespace std;
+  return is_constructible<shared_ptr<To>, auto_ptr<From>>::value
+    && is_constructible<shared_ptr<const To>, auto_ptr<From>>::value
+    && is_constructible<shared_ptr<const To>, auto_ptr<const From>>::value;
+}
+
+static_assert(  constructible< A,   A    >(), "A -> A compatible" );
+static_assert(  constructible< B,   A    >(), "B -> A compatible" );
+static_assert(  constructible< int, int  >(), "int -> int compatible" );
+static_assert( !constructible< int, long >(), "int -> long not compatible" );
+
+void
 test01()
 {
   std::auto_ptr<A> a(new A);
@@ -36,13 +54,24 @@ test01()
   VERIFY( a.get() == 0 );
   VERIFY( a2.get() != 0 );
   VERIFY( a2.use_count() == 1 );
+}
 
-  return 0;
+void
+test02()
+{
+  std::auto_ptr<B> b(new B);
+  std::shared_ptr<A> a(std::move(b));
+  VERIFY( b.get() == 0 );
+  VERIFY( a.get() != 0 );
+  VERIFY( a.use_count() == 1 );
+  a.reset();
+  VERIFY( destroyed == 1 );
 }
 
 int
 main()
 {
   test01();
+  test02();
   return 0;
 }
index 18e66162754d7f2a7ff5bcde274992e63d81ecbf..52bbd3b0e464f1456f6b1a72c827c9929f9844a4 100644 (file)
 
 struct A { };
 
+int destroyed = 0;
+struct B : A { ~B() { ++destroyed; } };
+
 // 20.7.2.2.1 shared_ptr constructors [util.smartptr.shared.const]
 
 // Construction from unique_ptr
-int
+
+template<typename From, typename To>
+constexpr bool constructible()
+{
+  using namespace std;
+  return is_constructible<shared_ptr<To>, unique_ptr<From>>::value
+    && is_constructible<shared_ptr<const To>, unique_ptr<From>>::value
+    && is_constructible<shared_ptr<const To>, unique_ptr<const From>>::value;
+}
+
+static_assert(  constructible< A,   A    >(), "A -> A compatible" );
+static_assert(  constructible< B,   A    >(), "B -> A compatible" );
+static_assert(  constructible< int, int  >(), "int -> int compatible" );
+static_assert( !constructible< int, long >(), "int -> long not compatible" );
+
+void
 test01()
 {
   std::unique_ptr<A> up(new A);
@@ -35,13 +53,24 @@ test01()
   VERIFY( up.get() == 0 );
   VERIFY( sp.get() != 0 );
   VERIFY( sp.use_count() == 1 );
+}
 
-  return 0;
+void
+test02()
+{
+  std::unique_ptr<B> b(new B);
+  std::shared_ptr<A> a(std::move(b));
+  VERIFY( b.get() == 0 );
+  VERIFY( a.get() != 0 );
+  VERIFY( a.use_count() == 1 );
+  a.reset();
+  VERIFY( destroyed == 1 );
 }
 
 int
 main()
 {
   test01();
+  test02();
   return 0;
 }
index 0cadf25bffbe51bff46a9d87751e7498ac3b1b0b..ba2864499123f41dc640f2e5314fc2e32be21f61 100644 (file)
@@ -26,3 +26,7 @@ void test01()
   std::shared_ptr<void> p((void*)nullptr);   // { dg-error "here" }
   // { dg-error "incomplete" "" { target *-*-* } 0 }
 }
+
+using std::shared_ptr;
+using std::is_constructible;
+static_assert(!is_constructible<shared_ptr<void>, const void*>::value, "");