diff mbox

LWG DR 2315. weak_ptr should be movable

Message ID 20141112115406.GU5191@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Nov. 12, 2014, 11:54 a.m. UTC
http://cplusplus.github.io/LWG/lwg-defects.html#2315

Tested x86_64-linux and ppc64-linux, committed to trunk.
diff mbox

Patch

commit d362afb7d30cbf9b138c162050376f1491a5c6f5
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Feb 10 18:15:08 2014 -0800

    LWG DR 2315. weak_ptr should be movable
    
    	* include/bits/shared_ptr.h (weak_ptr): Add move constructor and
    	assignment.
    	* include/bits/shared_ptr_base.h (__weak_count, __weak_ptr): Likewise.
    	Use nullptr and injected class name.
    	* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error.
    	* testsuite/20_util/shared_ptr/cons/void_neg.cc: Adjust dg-error.

diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index f611e53..c2d56eb 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -465,19 +465,30 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     class weak_ptr : public __weak_ptr<_Tp>
     {
     public:
-      constexpr weak_ptr() noexcept
-      : __weak_ptr<_Tp>() { }
+      constexpr weak_ptr() noexcept = default;
 
       template<typename _Tp1, typename = typename
 	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
-	weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
+	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>
-	weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
+	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>
+	weak_ptr(weak_ptr<_Tp1>&& __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
@@ -494,6 +505,17 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  return *this;
 	}
 
+      weak_ptr&
+      operator=(weak_ptr&& __r) noexcept = default;
+
+      template<typename _Tp1>
+	weak_ptr&
+	operator=(weak_ptr<_Tp1>&& __r) noexcept
+	{
+	  this->__weak_ptr<_Tp>::operator=(std::move(__r));
+	  return *this;
+	}
+
       shared_ptr<_Tp>
       lock() const noexcept
       { return shared_ptr<_Tp>(*this, std::nothrow); }
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index 6f85ffa..ea74000 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -721,55 +721,69 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     class __weak_count
     {
     public:
-      constexpr __weak_count() noexcept : _M_pi(0)
+      constexpr __weak_count() noexcept : _M_pi(nullptr)
       { }
 
       __weak_count(const __shared_count<_Lp>& __r) noexcept
       : _M_pi(__r._M_pi)
       {
-	if (_M_pi != 0)
+	if (_M_pi != nullptr)
 	  _M_pi->_M_weak_add_ref();
       }
 
-      __weak_count(const __weak_count<_Lp>& __r) noexcept
+      __weak_count(const __weak_count& __r) noexcept
       : _M_pi(__r._M_pi)
       {
-	if (_M_pi != 0)
+	if (_M_pi != nullptr)
 	  _M_pi->_M_weak_add_ref();
       }
 
+      __weak_count(__weak_count&& __r) noexcept
+      : _M_pi(__r._M_pi)
+      { __r._M_pi = nullptr; }
+
       ~__weak_count() noexcept
       {
-	if (_M_pi != 0)
+	if (_M_pi != nullptr)
 	  _M_pi->_M_weak_release();
       }
 
-      __weak_count<_Lp>&
+      __weak_count&
       operator=(const __shared_count<_Lp>& __r) noexcept
       {
 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
-	if (__tmp != 0)
+	if (__tmp != nullptr)
 	  __tmp->_M_weak_add_ref();
-	if (_M_pi != 0)
+	if (_M_pi != nullptr)
 	  _M_pi->_M_weak_release();
 	_M_pi = __tmp;
 	return *this;
       }
 
-      __weak_count<_Lp>&
-      operator=(const __weak_count<_Lp>& __r) noexcept
+      __weak_count&
+      operator=(const __weak_count& __r) noexcept
       {
 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
-	if (__tmp != 0)
+	if (__tmp != nullptr)
 	  __tmp->_M_weak_add_ref();
-	if (_M_pi != 0)
+	if (_M_pi != nullptr)
 	  _M_pi->_M_weak_release();
 	_M_pi = __tmp;
 	return *this;
       }
 
+      __weak_count&
+      operator=(__weak_count&& __r) noexcept
+      {
+	if (_M_pi != nullptr)
+	  _M_pi->_M_weak_release();
+	_M_pi = __r._M_pi;
+        __r._M_pi = nullptr;
+	return *this;
+      }
+
       void
-      _M_swap(__weak_count<_Lp>& __r) noexcept
+      _M_swap(__weak_count& __r) noexcept
       {
 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
 	__r._M_pi = _M_pi;
@@ -778,7 +792,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       long
       _M_get_use_count() const noexcept
-      { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
+      { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
 
       bool
       _M_less(const __weak_count& __rhs) const noexcept
@@ -1321,11 +1335,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef _Tp element_type;
 
       constexpr __weak_ptr() noexcept
-      : _M_ptr(0), _M_refcount()
+      : _M_ptr(nullptr), _M_refcount()
       { }
 
       __weak_ptr(const __weak_ptr&) noexcept = default;
-      __weak_ptr& operator=(const __weak_ptr&) noexcept = default;
+
       ~__weak_ptr() = default;
 
       // The "obvious" converting constructor implementation:
@@ -1354,6 +1368,19 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
 	{ }
 
+      __weak_ptr(__weak_ptr&& __r) noexcept
+      : _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>
+	__weak_ptr(__weak_ptr<_Tp1, _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
@@ -1372,6 +1399,25 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  return *this;
 	}
 
+      __weak_ptr&
+      operator=(__weak_ptr&& __r) noexcept
+      {
+	_M_ptr = __r._M_ptr;
+	_M_refcount = std::move(__r._M_refcount);
+	__r._M_ptr = nullptr;
+	return *this;
+      }
+
+      template<typename _Tp1>
+	__weak_ptr&
+	operator=(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
+	{
+	  _M_ptr = __r.lock().get();
+	  _M_refcount = std::move(__r._M_refcount);
+	  __r._M_ptr = nullptr;
+	  return *this;
+	}
+
       __shared_ptr<_Tp, _Lp>
       lock() const noexcept
       { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
index 8bbb591..be33279 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
@@ -32,7 +32,7 @@  void test01()
 {
   X* px = 0;
   std::shared_ptr<X> p1(px);   // { dg-error "here" }
-  // { dg-error "incomplete" "" { target *-*-* } 864 }
+  // { dg-error "incomplete" "" { target *-*-* } 878 }
 
   std::shared_ptr<X> p9(ap());  // { dg-error "here" }
   // { dg-error "incomplete" "" { target *-*-* } 307 }
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 1ea114c..17e036f 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
@@ -25,5 +25,5 @@ 
 void test01()
 {
   std::shared_ptr<void> p((void*)nullptr);   // { dg-error "here" }
-  // { dg-error "incomplete" "" { target *-*-* } 863 }
+  // { dg-error "incomplete" "" { target *-*-* } 877 }
 }