This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch, v7] libstdc++/24617 (was: Re: [Patch] libstdc++/23425)


Howard Hinnant wrote:

> clear() is best not thought of as a special case of erase().  It is 
> best thought of as a special case of a private function which I'll call:
>
> void __erase_at_end(size_type n);
>
> Erases the last n elements from the vector.  This is needed in the 
> following public members of vector:
>
> All forms of assign.
> All forms of erase.
> All forms of resize.
> clear.

The below implements Howard's suggestion in the v7-branch. Needless to
say, I like the idea a lot, and, assuming we agree on the
implementation, after some additional testing I'm in favor of having an
appropriate version of it also in 4.1.x (x > 0). Tested x86-linux.

Paolo.

///////////////////
2005-11-02  Paolo Carlini  <pcarlini@suse.de>

	PR libstdc++/24617
	* include/bits/stl_vector.h (vector<>::_M_erase_at_end): New.
	(vector<>::clear, resize): Use it.
	* include/bits/vector.tcc (vector<>::erase(iterator, iterator),
	_M_fill_assign, _M_assign_aux): Likewise.

	* testsuite/23_containers/vector/modifiers/erase/1.cc: New.
Index: include/bits/stl_vector.h
===================================================================
--- include/bits/stl_vector.h	(revision 105943)
+++ include/bits/stl_vector.h	(working copy)
@@ -451,7 +451,7 @@
       resize(size_type __new_size, value_type __x = value_type())
       {
 	if (__new_size < size())
-	  erase(begin() + __new_size, end());
+	  _M_erase_at_end(begin() + __new_size);
 	else
 	  insert(end(), __new_size - size(), __x);
       }
@@ -800,7 +800,7 @@
        */
       void
       clear()
-      { erase(begin(), end()); }
+      { _M_erase_at_end(begin()); }
 
     protected:
       /**
@@ -903,7 +903,6 @@
 					_M_get_Tp_allocator());
 	}
 
-
       // Internal assign functions follow.  The *_aux functions do the actual
       // assignment work for the range versions.
 
@@ -989,6 +988,19 @@
       template<typename _Value>
 	void
 	_M_insert_aux(iterator __position, const _Value&);
+
+
+      // Internal erase functions follow.
+
+      // Called by erase(q1,q2), clear(), resize(), _M_fill_assign,
+      // _M_assign_aux.
+      void
+      _M_erase_at_end(iterator __pos)
+      {
+	std::_Destroy(__pos.base(), this->_M_impl._M_finish,
+		      _M_get_Tp_allocator());
+	this->_M_impl._M_finish = __pos.base();
+      }
     };
 
 
Index: include/bits/vector.tcc
===================================================================
--- include/bits/vector.tcc	(revision 105943)
+++ include/bits/vector.tcc	(working copy)
@@ -121,9 +121,9 @@
     vector<_Tp, _Alloc>::
     erase(iterator __first, iterator __last)
     {
-      iterator __i(std::__move(__last, end(), __first));
-      std::_Destroy(__i, end(), _M_get_Tp_allocator());
-      this->_M_impl._M_finish = this->_M_impl._M_finish - (__last - __first);
+      if (__last != end())
+	std::__move(__last, end(), __first);
+      _M_erase_at_end(__first + (end() - __last));
       return __first;
     }
 
@@ -184,7 +184,7 @@
 	  this->_M_impl._M_finish += __n - size();
 	}
       else
-        erase(fill_n(begin(), __n, __val), end());
+        _M_erase_at_end(std::fill_n(begin(), __n, __val));
     }
 
   template<typename _Tp, typename _Alloc>
@@ -198,7 +198,7 @@
 	for (; __first != __last && __cur != end(); ++__cur, ++__first)
 	  *__cur = *__first;
 	if (__first == __last)
-	  erase(__cur, end());
+	  _M_erase_at_end(__cur);
 	else
 	  insert(end(), __first, __last);
       }
@@ -227,9 +227,8 @@
 	else if (size() >= __len)
 	  {
 	    iterator __new_finish(std::copy(__first, __last,
-				       this->_M_impl._M_start));
-	    std::_Destroy(__new_finish, end(), _M_get_Tp_allocator());
-	    this->_M_impl._M_finish = __new_finish.base();
+					    this->_M_impl._M_start));
+	    _M_erase_at_end(__new_finish);
 	  }
 	else
 	  {
Index: testsuite/23_containers/vector/modifiers/erase/1.cc
===================================================================
--- testsuite/23_containers/vector/modifiers/erase/1.cc	(revision 0)
+++ testsuite/23_containers/vector/modifiers/erase/1.cc	(revision 0)
@@ -0,0 +1,102 @@
+// 2005-11-02  Paolo Carlini  <pcarlini@suse.de>
+
+// Copyright (C) 2005 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 23.2.4.3 vector modifiers
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+const int  A[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+const int A1[] = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+const int A2[] = {0, 2, 3, 4, 10, 11, 12, 13, 14, 15};
+const int A3[] = {0, 2, 3, 4, 10, 11};
+const int  N = sizeof(A)  / sizeof(int);
+const int N1 = sizeof(A1) / sizeof(int);
+const int N2 = sizeof(A2) / sizeof(int);
+const int N3 = sizeof(A3) / sizeof(int);
+
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  typedef std::vector<int>   vec_type;
+  typedef vec_type::iterator iterator_type;
+
+  vec_type v(A, A + N);
+
+  iterator_type it1 = v.erase(v.begin() + 1);
+  VERIFY( it1 == v.begin() + 1 );
+  VERIFY( std::equal(v.begin(), v.end(), A1) );
+  
+  iterator_type it2 = v.erase(v.begin() + 4, v.begin() + 9);
+  VERIFY( it2 == v.begin() + 4 );
+  VERIFY( std::equal(v.begin(), v.end(), A2) );
+  
+  iterator_type it3 = v.erase(v.begin() + 6, v.end());
+  VERIFY( it3 == v.begin() + 6 );
+  VERIFY( std::equal(v.begin(), v.end(), A3) );
+
+  iterator_type it4 = v.erase(v.begin(), v.end());
+  VERIFY( it4 == v.begin() );
+  VERIFY( v.empty() );
+}
+
+void
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  typedef std::vector<std::vector<int> >   vec_type;
+  typedef vec_type::iterator          iterator_type;
+
+  vec_type v, v1, v2, v3, v4;
+  for (int i = 0; i < N; ++i)
+    v.push_back(std::vector<int>(1, A[i]));
+  for (int i = 0; i < N1; ++i)
+    v1.push_back(std::vector<int>(1, A1[i]));
+  for (int i = 0; i < N2; ++i)
+    v2.push_back(std::vector<int>(1, A2[i]));
+  for (int i = 0; i < N3; ++i)
+    v3.push_back(std::vector<int>(1, A3[i]));
+  
+  iterator_type it1 = v.erase(v.begin() + 1);
+  VERIFY( it1 == v.begin() + 1 );
+  VERIFY( std::equal(v.begin(), v.end(), v1.begin()) );
+  
+  iterator_type it2 = v.erase(v.begin() + 4, v.begin() + 9);
+  VERIFY( it2 == v.begin() + 4 );
+  VERIFY( std::equal(v.begin(), v.end(), v2.begin()) );
+  
+  iterator_type it3 = v.erase(v.begin() + 6, v.end());
+  VERIFY( it3 == v.begin() + 6 );
+  VERIFY( std::equal(v.begin(), v.end(), v3.begin()) );
+
+  iterator_type it4 = v.erase(v.begin(), v.end());
+  VERIFY( it4 == v.begin() );
+  VERIFY( v.empty() );
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]