This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[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;
+}