* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error.
* testsuite/20_util/shared_ptr/cons/void_neg.cc: Adjust dg-error.
+ * include/bits/shared_ptr.h (shared_ptr, weak_ptr): Define
+ _Convertible alias template to simplify constraints.
+ (shared_ptr(unique_ptr<TD>&&)): Constrain (LWG 2399).
+ * include/bits/shared_ptr_base.h: Likewise.
+ (_Sp_counted_deleter::_M_get_deleter()): Use addressof (LWG 2400).
+ * include/std/functional (function::operator=(nullptr_t)): Add
+ noexcept (LWG 2401).
+ * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error.
+ * testsuite/20_util/shared_ptr/cons/void_neg.cc: Adjust dg-error.
+
2014-11-12 Jonathan Wakely <jwakely@redhat.com>
PR c++/33911
template<typename _Tp>
class shared_ptr : public __shared_ptr<_Tp>
{
+ template<typename _Ptr>
+ using _Convertible
+ = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
public:
/**
* @brief Construct an empty %shared_ptr.
* @param __r A %shared_ptr.
* @post get() == __r.get() && use_count() == __r.use_count()
*/
- template<typename _Tp1, typename = typename
- std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+ template<typename _Tp1, typename = _Convertible<_Tp1*>>
shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
: __shared_ptr<_Tp>(__r) { }
* @param __r A %shared_ptr rvalue.
* @post *this contains the old value of @a __r, @a __r is empty.
*/
- template<typename _Tp1, typename = typename
- std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+ template<typename _Tp1, typename = _Convertible<_Tp1*>>
shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
: __shared_ptr<_Tp>(std::move(__r)) { }
shared_ptr(std::auto_ptr<_Tp1>&& __r);
#endif
- template<typename _Tp1, typename _Del>
+ // _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)
: __shared_ptr<_Tp>(std::move(__r)) { }
template<typename _Tp>
class weak_ptr : public __weak_ptr<_Tp>
{
+ template<typename _Ptr>
+ using _Convertible
+ = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
public:
constexpr weak_ptr() noexcept = default;
- template<typename _Tp1, typename = typename
- std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+ template<typename _Tp1, typename = _Convertible<_Tp1*>>
weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
: __weak_ptr<_Tp>(__r) { }
weak_ptr(const weak_ptr&) noexcept = default;
- template<typename _Tp1, typename = typename
- std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+ template<typename _Tp1, typename = _Convertible<_Tp1*>>
weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
: __weak_ptr<_Tp>(__r) { }
weak_ptr(weak_ptr&&) noexcept = default;
- template<typename _Tp1, typename = typename
- std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+ template<typename _Tp1, typename = _Convertible<_Tp1*>>
weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
: __weak_ptr<_Tp>(std::move(__r)) { }
_M_get_deleter(const std::type_info& __ti) noexcept
{
#ifdef __GXX_RTTI
- return __ti == typeid(_Deleter) ? &_M_impl._M_del() : nullptr;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2400. shared_ptr's get_deleter() should use addressof()
+ return __ti == typeid(_Deleter)
+ ? std::__addressof(_M_impl._M_del())
+ : nullptr;
#else
return nullptr;
#endif
template<typename _Tp, _Lock_policy _Lp>
class __shared_ptr
{
+ template<typename _Ptr>
+ using _Convertible
+ = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
public:
typedef _Tp element_type;
__shared_ptr& operator=(const __shared_ptr&) noexcept = default;
~__shared_ptr() = default;
- template<typename _Tp1, typename = typename
- std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+ template<typename _Tp1, typename = _Convertible<_Tp1*>>
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
{ }
__r._M_ptr = 0;
}
- template<typename _Tp1, typename = typename
- std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+ template<typename _Tp1, typename = _Convertible<_Tp1*>>
__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount()
{
}
// If an exception is thrown this constructor has no effect.
- template<typename _Tp1, typename _Del>
+ template<typename _Tp1, typename _Del, typename
+ = _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
: _M_ptr(__r.get()), _M_refcount()
{
template<typename _Tp, _Lock_policy _Lp>
class __weak_ptr
{
+ template<typename _Ptr>
+ using _Convertible
+ = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
public:
typedef _Tp element_type;
//
// 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 = typename
- std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+ template<typename _Tp1, typename = _Convertible<_Tp1*>>
__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
: _M_refcount(__r._M_refcount)
{ _M_ptr = __r.lock().get(); }
- template<typename _Tp1, typename = typename
- std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+ template<typename _Tp1, typename = _Convertible<_Tp1*>>
__weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
{ }
: _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
{ __r._M_ptr = nullptr; }
- template<typename _Tp1, typename = typename
- std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+ template<typename _Tp1, typename = _Convertible<_Tp1*>>
__weak_ptr(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
: _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
{ __r._M_ptr = nullptr; }
* The target of @c *this is deallocated, leaving it empty.
*/
function&
- operator=(nullptr_t)
+ operator=(nullptr_t) noexcept
{
if (_M_manager)
{
{
X* px = 0;
std::shared_ptr<X> p1(px); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 878 }
+ // { dg-error "incomplete" "" { target *-*-* } 886 }
std::shared_ptr<X> p9(ap()); // { dg-error "here" }
// { dg-error "incomplete" "" { target *-*-* } 307 }
void test01()
{
std::shared_ptr<void> p((void*)nullptr); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 877 }
+ // { dg-error "incomplete" "" { target *-*-* } 885 }
}