diff mbox

[v3] PR libstdc++/49561

Message ID 4E8B8773.9020301@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Oct. 4, 2011, 10:23 p.m. UTC
Hi,

this simply implements the O(1) size for the C++0x std::list. Tested 
x86_64-linux multilib, etc, committed to mainline.

Thanks,
Paolo.

//////////////////////
2011-10-04  Paolo Carlini  <paolo.carlini@oracle.com>

	PR libstdc++/49561
	* include/bits/stl_list.h (_List_base<>::_List_impl::_M_size):
	Add in C++0x mode.
	(_List_base<>::_List_impl, _List_base<>::_M_get_node,
	_List_base<>::_M_put_node, _List_base<>::_List_base(_List_base&&),
	list<>::size, list<>::swap, list<>::splice): Use it.
	(operator==(const list<>&, const list<>&)): Rewrite in C++0x mode.
	* include/bits/list.tcc (list<>::erase): Likewise.
	(list<>::merge): Adjust in C++0x mode.
	* testsuite/23_containers/list/requirements/dr438/assign_neg.cc:
	Adjust dg-error line number.
	* testsuite/23_containers/list/requirements/dr438/insert_neg.cc:
	Likewise.
	* testsuite/23_containers/list/requirements/dr438/
	constructor_1_neg.cc: Likewise.
	* testsuite/23_containers/list/requirements/dr438/
	constructor_2_neg.cc: Likewise.
diff mbox

Patch

Index: include/bits/stl_list.h
===================================================================
--- include/bits/stl_list.h	(revision 179522)
+++ include/bits/stl_list.h	(working copy)
@@ -311,17 +311,27 @@ 
       {
 	__detail::_List_node_base _M_node;
 
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	size_t                    _M_size;
+#endif
+
 	_List_impl()
 	: _Node_alloc_type(), _M_node()
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	, _M_size(0)
+#endif
 	{ }
 
 	_List_impl(const _Node_alloc_type& __a)
 	: _Node_alloc_type(__a), _M_node()
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	, _M_size(0)
+#endif
 	{ }
 
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
 	_List_impl(_Node_alloc_type&& __a)
-	: _Node_alloc_type(std::move(__a)), _M_node()
+	: _Node_alloc_type(std::move(__a)), _M_node(), _M_size(0)
 	{ }
 #endif
       };
@@ -330,22 +340,33 @@ 
 
       _List_node<_Tp>*
       _M_get_node()
-      { return _M_impl._Node_alloc_type::allocate(1); }
-      
+      {
+	_List_node<_Tp>* __tmp = _M_impl._Node_alloc_type::allocate(1);
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	++_M_impl._M_size;
+#endif	
+	return __tmp;
+      }
+
       void
       _M_put_node(_List_node<_Tp>* __p)
-      { _M_impl._Node_alloc_type::deallocate(__p, 1); }
+      {
+	_M_impl._Node_alloc_type::deallocate(__p, 1);
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	--_M_impl._M_size;
+#endif
+      }
       
   public:
       typedef _Alloc allocator_type;
 
       _Node_alloc_type&
       _M_get_Node_allocator() _GLIBCXX_NOEXCEPT
-      { return *static_cast<_Node_alloc_type*>(&this->_M_impl); }
+      { return *static_cast<_Node_alloc_type*>(&_M_impl); }
 
       const _Node_alloc_type&
       _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT
-      { return *static_cast<const _Node_alloc_type*>(&this->_M_impl); }
+      { return *static_cast<const _Node_alloc_type*>(&_M_impl); }
 
       _Tp_alloc_type
       _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT
@@ -368,8 +389,8 @@ 
       : _M_impl(std::move(__x._M_get_Node_allocator()))
       {
 	_M_init();
-	__detail::_List_node_base::swap(this->_M_impl._M_node, 
-					__x._M_impl._M_node);	
+	__detail::_List_node_base::swap(_M_impl._M_node, __x._M_impl._M_node);
+	std::swap(_M_impl._M_size, __x._M_impl._M_size);
       }
 #endif
 
@@ -851,7 +872,13 @@ 
       /**  Returns the number of elements in the %list.  */
       size_type
       size() const _GLIBCXX_NOEXCEPT
-      { return std::distance(begin(), end()); }
+      {
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	return this->_M_impl._M_size;
+#else
+	return std::distance(begin(), end());
+#endif
+      }
 
       /**  Returns the size() of the largest possible %list.  */
       size_type
@@ -1186,6 +1213,9 @@ 
       {
 	__detail::_List_node_base::swap(this->_M_impl._M_node, 
 					__x._M_impl._M_node);
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	std::swap(this->_M_impl._M_size, __x._M_impl._M_size);
+#endif
 
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 431. Swapping containers with unequal allocators.
@@ -1230,6 +1260,11 @@ 
 	    _M_check_equal_allocators(__x);
 
 	    this->_M_transfer(__position, __x.begin(), __x.end());
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	    this->_M_impl._M_size += __x.size();
+	    __x._M_impl._M_size = 0;
+#endif
 	  }
       }
 
@@ -1261,8 +1296,15 @@ 
 	  return;
 
 	if (this != &__x)
-	  _M_check_equal_allocators(__x);
+	  {
+	    _M_check_equal_allocators(__x);
 
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	    ++this->_M_impl._M_size;
+	    --__x._M_impl._M_size;
+#endif
+	  }
+
 	this->_M_transfer(__position, __i, __j);
       }
 
@@ -1296,8 +1338,16 @@ 
 	if (__first != __last)
 	  {
 	    if (this != &__x)
-	      _M_check_equal_allocators(__x);
+	      {
+		_M_check_equal_allocators(__x);
 
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+		const size_type __size = std::distance(__first, __last);
+		this->_M_impl._M_size += __size;
+		__x._M_impl._M_size -= __size;
+#endif
+	      }
+
 	    this->_M_transfer(__position, __first, __last);
 	  }
       }
@@ -1571,6 +1621,10 @@ 
     inline bool
     operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
     {
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      return (__x.size() == __y.size()
+	      && std::equal(__x.begin(), __x.end(), __y.begin()));
+#else
       typedef typename list<_Tp, _Alloc>::const_iterator const_iterator;
       const_iterator __end1 = __x.end();
       const_iterator __end2 = __y.end();
@@ -1583,6 +1637,7 @@ 
 	  ++__i2;
 	}
       return __i1 == __end1 && __i2 == __end2;
+#endif
     }
 
   /**
Index: include/bits/list.tcc
===================================================================
--- include/bits/list.tcc	(revision 179522)
+++ include/bits/list.tcc	(working copy)
@@ -67,8 +67,8 @@ 
     _M_clear()
     {
       typedef _List_node<_Tp>  _Node;
-      _Node* __cur = static_cast<_Node*>(this->_M_impl._M_node._M_next);
-      while (__cur != &this->_M_impl._M_node)
+      _Node* __cur = static_cast<_Node*>(_M_impl._M_node._M_next);
+      while (__cur != &_M_impl._M_node)
 	{
 	  _Node* __tmp = __cur;
 	  __cur = static_cast<_Node*>(__cur->_M_next);
@@ -139,14 +139,14 @@ 
     list<_Tp, _Alloc>::
     resize(size_type __new_size)
     {
-      iterator __i = begin();
-      size_type __len = 0;
-      for (; __i != end() && __len < __new_size; ++__i, ++__len)
-        ;
-      if (__len == __new_size)
-        erase(__i, end());
-      else                          // __i == end()
-	_M_default_append(__new_size - __len);
+      if (__new_size > size())
+	_M_default_append(__new_size - size());
+      else if (__new_size < size())
+	{
+	  iterator __i = begin();
+	  std::advance(__i, __new_size);
+	  erase(__i, end());
+	}
     }
 
   template<typename _Tp, typename _Alloc>
@@ -154,14 +154,14 @@ 
     list<_Tp, _Alloc>::
     resize(size_type __new_size, const value_type& __x)
     {
-      iterator __i = begin();
-      size_type __len = 0;
-      for (; __i != end() && __len < __new_size; ++__i, ++__len)
-        ;
-      if (__len == __new_size)
-        erase(__i, end());
-      else                          // __i == end()
-        insert(end(), __new_size - __len, __x);
+      if (__new_size > size())
+	insert(end(), __new_size - size(), __x);
+      else if (__new_size < size())
+	{
+	  iterator __i = begin();
+	  std::advance(__i, __new_size);
+	  erase(__i, end());
+	}
     }
 #else
   template<typename _Tp, typename _Alloc>
@@ -312,6 +312,11 @@ 
 	      ++__first1;
 	  if (__first2 != __last2)
 	    _M_transfer(__last1, __first2, __last2);
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	  this->_M_impl._M_size += __x.size();
+	  __x._M_impl._M_size = 0;
+#endif
 	}
     }
 
@@ -346,6 +351,11 @@ 
 		++__first1;
 	    if (__first2 != __last2)
 	      _M_transfer(__last1, __first2, __last2);
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+	    this->_M_impl._M_size += __x.size();
+	    __x._M_impl._M_size = 0;
+#endif
 	  }
       }
 
Index: testsuite/23_containers/list/requirements/dr438/assign_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/assign_neg.cc	(revision 179522)
+++ testsuite/23_containers/list/requirements/dr438/assign_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1499 }
+// { dg-error "no matching" "" { target *-*-* } 1549 }
 
 #include <list>
 
Index: testsuite/23_containers/list/requirements/dr438/insert_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/insert_neg.cc	(revision 179522)
+++ testsuite/23_containers/list/requirements/dr438/insert_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1455 }
+// { dg-error "no matching" "" { target *-*-* } 1505 }
 
 #include <list>
 
Index: testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc	(revision 179522)
+++ testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1455 }
+// { dg-error "no matching" "" { target *-*-* } 1505 }
 
 #include <list>
 
Index: testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc	(revision 179522)
+++ testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1455 }
+// { dg-error "no matching" "" { target *-*-* } 1505 }
 
 #include <list>
 #include <utility>