This patch doesn't change very much, except for adding
std::reinterpret_pointer_cast, but it makes it very easy to add array
support to shared_ptr, as defined for the Library Fundamentals TS by
https://wg21.link/n3920 and in the process of being added to C++17 by
https://wg21.link/p0414r1

The main change is to consistently constrain all template constructors
and assignment operators. In std::shared_ptr we just forward the
checks to the std::__shared_ptr base class, so all the hard work is
done there. The base uses traits that can easily be extended to handle
array types without touching the uses of those traits (I have that
patch ready).

We also need to use shared_ptr<T>::element_type* in several places
where we use T* today, because when T is an array type they are not
the same thing. e.g. shared_ptr<int[]>::get() return int* not int[]*.

In practical terms this changes very little, just makes some invalid
code SFINAE-able instead of giving errors during instantiation, and
gives a nicer static assertion message for invalid deleters.

        * 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.

Tested powerpc64le-linux and x86_64-linux, and also tested with the
libc++ and (parts of) the boost::shared_ptr tests.

Committed to trunk.



commit 5e235c9782617f0b519f2273933ac257236c5e82
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Wed Oct 19 23:12:32 2016 +0100

    Prepare shared_ptr for array support
    
        * 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.

diff --git a/libstdc++-v3/include/backward/auto_ptr.h 
b/libstdc++-v3/include/backward/auto_ptr.h
index 94911c8..855b6f9 100644
--- a/libstdc++-v3/include/backward/auto_ptr.h
+++ b/libstdc++-v3/include/backward/auto_ptr.h
@@ -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)) { }
diff --git a/libstdc++-v3/include/bits/shared_ptr.h 
b/libstdc++-v3/include/bits/shared_ptr.h
index 9b9261c..9f7a40c 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -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())); }
-
-  template<typename _Tp, typename _Tp1>
-    inline shared_ptr<_Tp>
-    const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
-    { return shared_ptr<_Tp>(__r, const_cast<_Tp*>(__r.get())); }
-
-  template<typename _Tp, typename _Tp1>
-    inline shared_ptr<_Tp>
-    dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
+    static_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>;
+      return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
     }
 
+  template<typename _Tp, typename _Up>
+    inline shared_ptr<_Tp>
+    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 _Up>
+    inline shared_ptr<_Tp>
+    dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
+    {
+      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;
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h 
b/libstdc++-v3/include/bits/shared_ptr_base.h
index c0686ad..c74c92a 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -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.
     };
 
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc 
b/libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc
index 56d818e..0558cf4 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc
@@ -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
index 0000000..e519f0e
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/casts/reinterpret.cc
@@ -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));
+}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr.cc 
b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr.cc
index 7a99490..52481c1 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/auto_ptr.cc
@@ -25,10 +25,28 @@
 
 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;
 }
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc 
b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc
index 18e6616..52bbd3b 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc
@@ -24,10 +24,28 @@
 
 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;
 }
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc 
b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
index 0cadf25..ba28644 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
@@ -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, "");

Reply via email to