This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Deque... (Re: [Patch] libstdc++/23425)
Howard Hinnant wrote:
>>> FYI, I'm working on this. It looks like, we are already using the
>>> optimization for deque::clear() and we are not for
>>> deque::erase(iterator, iterator). It seems to me that we should just
>>> take out the code in clear() which implements the double loop pattern
>>> and call it from both. Which in fact would be _M_erase_at_end or
>>> _M_erase_at_begin ;) ...
>>
>> ... and of course, going to loops over plain pointers, instead of
>> deque::iterators means that _Destroy will be optimized very, very well
>> by the compiler, similarly to what happens for vector! (especially
>> so if
>> we overload it for random access iterators)
>>
>> :-)
>
> Thanks Paolo!
So, finally... Here is what I have, taking shape... Exactly as per
Howard's suggestions, the basic ideas are:
1- Consistently use _M_erase_at_begin/_M_erase_at_end and avoid calling
move/copy unnecessarily.
2- Consistently use the "segmented iterator" optimization, when nothing
better is available, that is, when _Destroy(iterator, iterator) doesn't
boil down for sure to nothing (see _M_destroy_data_aux).
I have verified from dumps that the loops over pointers produced by 2-
are optimized to empty loops as expected, even to nothing if _Destroy is
overloaded for random access iterators (but probably the additional
overloads can wait because the loop optimizer will be improved and we
have a PR about that opened by Chris, 23361). And of course that
otherwise the dumps are as good or better than current mainline ;)
Testcases ran through valgrind.
Anyone can spot something wrong? Otherwise I will probably go ahead for v7.
Paolo.
//////////////////
2005-11-26 Paolo Carlini <pcarlini@suse.de>
* include/bits/stl_deque.h (deque<>::_M_erase_at_end,
_M_erase_at_begin, _M_destroy_data, _M_destroy_data_dispatch,
_M_destroy_data_aux): New, optimize erase at begin() / end() and
consistently use the "segmented iterator" optimization.
(deque<>::~deque(), resize, clear, _M_assign_aux, _M_fill_assign):
Use the above.
* include/bits/deque.tcc (deque<>::operator=, _M_assign_aux): Same.
(erase(iterator, iterator)): Likewise, clean-up.
(erase(iterator)): Tweak, don't call __move unnecessarily.
(_M_destroy_data_aux): Define.
* testsuite/23_containers/deque/modifiers/erase/1.cc: New.
* testsuite/23_containers/deque/modifiers/erase/2.cc: Likewise.
* testsuite/23_containers/vector/modifiers/erase/1.cc: Extend.
Index: include/bits/stl_deque.h
===================================================================
--- include/bits/stl_deque.h (revision 106945)
+++ include/bits/stl_deque.h (working copy)
@@ -735,8 +735,7 @@
* way. Managing the pointer is the user's responsibilty.
*/
~deque()
- { std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
- _M_get_Tp_allocator()); }
+ { _M_destroy_data(begin(), end(), _M_get_Tp_allocator()); }
/**
* @brief %Deque assignment operator.
@@ -901,7 +900,7 @@
{
const size_type __len = size();
if (__new_size < __len)
- erase(this->_M_impl._M_start + __new_size, this->_M_impl._M_finish);
+ _M_erase_at_end(this->_M_impl._M_start + __new_size);
else
insert(this->_M_impl._M_finish, __new_size - __len, __x);
}
@@ -1268,7 +1267,9 @@
* pointed-to memory is not touched in any way. Managing the pointer is
* the user's responsibilty.
*/
- void clear();
+ void
+ clear()
+ { _M_erase_at_end(begin()); }
protected:
// Internal constructor functions follow.
@@ -1378,7 +1379,7 @@
insert(end(), __mid, __last);
}
else
- erase(std::copy(__first, __last, begin()), end());
+ _M_erase_at_end(std::copy(__first, __last, begin()));
}
// Called by assign(n,t), and the range assign when it turns out
@@ -1393,7 +1394,7 @@
}
else
{
- erase(begin() + __n, end());
+ _M_erase_at_end(begin() + __n);
std::fill(begin(), end(), __val);
}
}
@@ -1406,9 +1407,12 @@
*/
template<typename _Value_type>
void _M_push_back_aux(const _Value_type&);
+
template<typename _Value_type>
void _M_push_front_aux(const _Value_type&);
+
void _M_pop_back_aux();
+
void _M_pop_front_aux();
//@}
@@ -1470,6 +1474,54 @@
_ForwardIterator __first, _ForwardIterator __last,
size_type __n);
+
+ // Internal erase functions follow.
+
+ void
+ _M_destroy_data_aux(iterator __first, iterator __last);
+
+ void
+ _M_destroy_data_dispatch(iterator, iterator, __true_type) { }
+
+ void
+ _M_destroy_data_dispatch(iterator __first, iterator __last, __false_type)
+ { _M_destroy_data_aux(__first, __last); }
+
+ // Called by ~deque().
+ // NB: Doesn't deallocate the nodes.
+ template<typename _Alloc1>
+ void
+ _M_destroy_data(iterator __first, iterator __last, _Alloc1)
+ { _M_destroy_data_aux(__first, __last); }
+
+ void
+ _M_destroy_data(iterator __first, iterator __last, std::allocator<_Tp>)
+ {
+ typedef typename std::__is_scalar<value_type>::__type
+ _Has_trivial_destructor;
+ _M_destroy_data_dispatch(__first, __last, _Has_trivial_destructor());
+ }
+
+ // Called by erase(q1, q2).
+ void
+ _M_erase_at_begin(iterator __pos)
+ {
+ _M_destroy_data(begin(), __pos, _M_get_Tp_allocator());
+ _M_destroy_nodes(this->_M_impl._M_start._M_node, __pos._M_node);
+ this->_M_impl._M_start = __pos;
+ }
+
+ // Called by erase(q1, q2), resize(), clear(), _M_assign_aux,
+ // _M_fill_assign, operator=.
+ void
+ _M_erase_at_end(iterator __pos)
+ {
+ _M_destroy_data(__pos, end(), _M_get_Tp_allocator());
+ _M_destroy_nodes(__pos._M_node + 1,
+ this->_M_impl._M_finish._M_node + 1);
+ this->_M_impl._M_finish = __pos;
+ }
+
//@{
/**
* @if maint
Index: include/bits/deque.tcc
===================================================================
--- include/bits/deque.tcc (revision 106945)
+++ include/bits/deque.tcc (working copy)
@@ -72,8 +72,8 @@
if (&__x != this)
{
if (__len >= __x.size())
- erase(std::copy(__x.begin(), __x.end(), this->_M_impl._M_start),
- this->_M_impl._M_finish);
+ _M_erase_at_end(std::copy(__x.begin(), __x.end(),
+ this->_M_impl._M_start));
else
{
const_iterator __mid = __x.begin() + difference_type(__len);
@@ -112,18 +112,20 @@
{
iterator __next = __position;
++__next;
- const size_type __index = __position - this->_M_impl._M_start;
+ const size_type __index = __position - begin();
if (__index < (size() >> 1))
{
- std::__move_backward(this->_M_impl._M_start, __position, __next);
+ if (__position != begin())
+ std::__move_backward(begin(), __position, __next);
pop_front();
}
else
{
- std::__move(__next, this->_M_impl._M_finish, __position);
+ if (__next != end())
+ std::__move(__next, end(), __position);
pop_back();
}
- return this->_M_impl._M_start + __index;
+ return begin() + __index;
}
template<typename _Tp, typename _Alloc>
@@ -131,73 +133,31 @@
deque<_Tp, _Alloc>::
erase(iterator __first, iterator __last)
{
- if (__first == this->_M_impl._M_start
- && __last == this->_M_impl._M_finish)
+ if (__first == begin() && __last == end())
{
clear();
- return this->_M_impl._M_finish;
+ return end();
}
else
{
const difference_type __n = __last - __first;
- const difference_type __elems_before = (__first
- - this->_M_impl._M_start);
+ const difference_type __elems_before = __first - begin();
if (static_cast<size_type>(__elems_before) < (size() - __n) / 2)
{
- std::__move_backward(this->_M_impl._M_start, __first, __last);
- iterator __new_start = this->_M_impl._M_start + __n;
- std::_Destroy(this->_M_impl._M_start, __new_start,
- _M_get_Tp_allocator());
- _M_destroy_nodes(this->_M_impl._M_start._M_node,
- __new_start._M_node);
- this->_M_impl._M_start = __new_start;
+ if (__first != begin())
+ std::__move_backward(begin(), __first, __last);
+ _M_erase_at_begin(begin() + __n);
}
else
{
- std::__move(__last, this->_M_impl._M_finish, __first);
- iterator __new_finish = this->_M_impl._M_finish - __n;
- std::_Destroy(__new_finish, this->_M_impl._M_finish,
- _M_get_Tp_allocator());
- _M_destroy_nodes(__new_finish._M_node + 1,
- this->_M_impl._M_finish._M_node + 1);
- this->_M_impl._M_finish = __new_finish;
+ if (__last != end())
+ std::__move(__last, end(), __first);
+ _M_erase_at_end(end() - __n);
}
- return this->_M_impl._M_start + __elems_before;
+ return begin() + __elems_before;
}
}
- template<typename _Tp, typename _Alloc>
- void
- deque<_Tp, _Alloc>::
- clear()
- {
- for (_Map_pointer __node = this->_M_impl._M_start._M_node + 1;
- __node < this->_M_impl._M_finish._M_node;
- ++__node)
- {
- std::_Destroy(*__node, *__node + _S_buffer_size(),
- _M_get_Tp_allocator());
- _M_deallocate_node(*__node);
- }
-
- if (this->_M_impl._M_start._M_node != this->_M_impl._M_finish._M_node)
- {
- std::_Destroy(this->_M_impl._M_start._M_cur,
- this->_M_impl._M_start._M_last,
- _M_get_Tp_allocator());
- std::_Destroy(this->_M_impl._M_finish._M_first,
- this->_M_impl._M_finish._M_cur,
- _M_get_Tp_allocator());
- _M_deallocate_node(this->_M_impl._M_finish._M_first);
- }
- else
- std::_Destroy(this->_M_impl._M_start._M_cur,
- this->_M_impl._M_finish._M_cur,
- _M_get_Tp_allocator());
-
- this->_M_impl._M_finish = this->_M_impl._M_start;
- }
-
template<typename _Tp, class _Alloc>
template<typename _InputIterator>
void
@@ -209,7 +169,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);
}
@@ -682,6 +642,28 @@
template<typename _Tp, typename _Alloc>
void
deque<_Tp, _Alloc>::
+ _M_destroy_data_aux(iterator __first, iterator __last)
+ {
+ for (_Map_pointer __node = __first._M_node + 1;
+ __node < __last._M_node; ++__node)
+ std::_Destroy(*__node, *__node + _S_buffer_size(),
+ _M_get_Tp_allocator());
+
+ if (__first._M_node != __last._M_node)
+ {
+ std::_Destroy(__first._M_cur, __first._M_last,
+ _M_get_Tp_allocator());
+ std::_Destroy(__last._M_first, __last._M_cur,
+ _M_get_Tp_allocator());
+ }
+ else
+ std::_Destroy(__first._M_cur, __last._M_cur,
+ _M_get_Tp_allocator());
+ }
+
+ template<typename _Tp, typename _Alloc>
+ void
+ deque<_Tp, _Alloc>::
_M_new_elements_at_front(size_type __new_elems)
{
const size_type __new_nodes
Index: testsuite/23_containers/vector/modifiers/erase/1.cc
===================================================================
--- testsuite/23_containers/vector/modifiers/erase/1.cc (revision 106945)
+++ testsuite/23_containers/vector/modifiers/erase/1.cc (working copy)
@@ -27,10 +27,14 @@
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 A4[] = {4, 10, 11};
+const int A5[] = {4, 10};
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);
+const int N4 = sizeof(A4) / sizeof(int);
+const int N5 = sizeof(A4) / sizeof(int);
void
test01()
@@ -54,8 +58,16 @@
VERIFY( it3 == v.begin() + 6 );
VERIFY( std::equal(v.begin(), v.end(), A3) );
- iterator_type it4 = v.erase(v.begin(), v.end());
+ iterator_type it4 = v.erase(v.begin(), v.begin() + 3);
VERIFY( it4 == v.begin() );
+ VERIFY( std::equal(v.begin(), v.end(), A4) );
+
+ iterator_type it5 = v.erase(v.begin() + 2);
+ VERIFY( it5 == v.begin() + 2 );
+ VERIFY( std::equal(v.begin(), v.end(), A5) );
+
+ iterator_type it6 = v.erase(v.begin(), v.end());
+ VERIFY( it6 == v.begin() );
VERIFY( v.empty() );
}
@@ -67,7 +79,7 @@
typedef std::vector<std::vector<int> > vec_type;
typedef vec_type::iterator iterator_type;
- vec_type v, v1, v2, v3;
+ vec_type v, v1, v2, v3, v4, v5;
for (int i = 0; i < N; ++i)
v.push_back(std::vector<int>(1, A[i]));
for (int i = 0; i < N1; ++i)
@@ -76,6 +88,10 @@
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]));
+ for (int i = 0; i < N2; ++i)
+ v4.push_back(std::vector<int>(1, A4[i]));
+ for (int i = 0; i < N3; ++i)
+ v5.push_back(std::vector<int>(1, A5[i]));
iterator_type it1 = v.erase(v.begin() + 1);
VERIFY( it1 == v.begin() + 1 );
@@ -89,8 +105,16 @@
VERIFY( it3 == v.begin() + 6 );
VERIFY( std::equal(v.begin(), v.end(), v3.begin()) );
- iterator_type it4 = v.erase(v.begin(), v.end());
+ iterator_type it4 = v.erase(v.begin(), v.begin() + 3);
VERIFY( it4 == v.begin() );
+ VERIFY( std::equal(v.begin(), v.end(), v4.begin()) );
+
+ iterator_type it5 = v.erase(v.begin() + 2);
+ VERIFY( it5 == v.begin() + 2 );
+ VERIFY( std::equal(v.begin(), v.end(), v5.begin()) );
+
+ iterator_type it6 = v.erase(v.begin(), v.end());
+ VERIFY( it6 == v.begin() );
VERIFY( v.empty() );
}
Index: testsuite/23_containers/deque/modifiers/erase/1.cc
===================================================================
--- testsuite/23_containers/deque/modifiers/erase/1.cc (revision 0)
+++ testsuite/23_containers/deque/modifiers/erase/1.cc (revision 0)
@@ -0,0 +1,126 @@
+// 2005-11-25 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.1.3 deque modifiers
+
+#include <deque>
+#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 A4[] = {4, 10, 11};
+const int A5[] = {4, 10};
+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);
+const int N4 = sizeof(A4) / sizeof(int);
+const int N5 = sizeof(A4) / sizeof(int);
+
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef std::deque<int> deque_type;
+ typedef deque_type::iterator iterator_type;
+
+ deque_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.begin() + 3);
+ VERIFY( it4 == v.begin() );
+ VERIFY( std::equal(v.begin(), v.end(), A4) );
+
+ iterator_type it5 = v.erase(v.begin() + 2);
+ VERIFY( it5 == v.begin() + 2 );
+ VERIFY( std::equal(v.begin(), v.end(), A5) );
+
+ iterator_type it6 = v.erase(v.begin(), v.end());
+ VERIFY( it6 == v.begin() );
+ VERIFY( v.empty() );
+}
+
+void
+test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef std::deque<std::deque<int> > deque_type;
+ typedef deque_type::iterator iterator_type;
+
+ deque_type v, v1, v2, v3, v4, v5;
+ for (int i = 0; i < N; ++i)
+ v.push_back(std::deque<int>(1, A[i]));
+ for (int i = 0; i < N1; ++i)
+ v1.push_back(std::deque<int>(1, A1[i]));
+ for (int i = 0; i < N2; ++i)
+ v2.push_back(std::deque<int>(1, A2[i]));
+ for (int i = 0; i < N3; ++i)
+ v3.push_back(std::deque<int>(1, A3[i]));
+ for (int i = 0; i < N4; ++i)
+ v4.push_back(std::deque<int>(1, A4[i]));
+ for (int i = 0; i < N5; ++i)
+ v5.push_back(std::deque<int>(1, A5[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.begin() + 3);
+ VERIFY( it4 == v.begin() );
+ VERIFY( std::equal(v.begin(), v.end(), v4.begin()) );
+
+ iterator_type it5 = v.erase(v.begin() + 2);
+ VERIFY( it5 == v.begin() + 2 );
+ VERIFY( std::equal(v.begin(), v.end(), v5.begin()) );
+
+ iterator_type it6 = v.erase(v.begin(), v.end());
+ VERIFY( it6 == v.begin() );
+ VERIFY( v.empty() );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
Index: testsuite/23_containers/deque/modifiers/erase/2.cc
===================================================================
--- testsuite/23_containers/deque/modifiers/erase/2.cc (revision 0)
+++ testsuite/23_containers/deque/modifiers/erase/2.cc (revision 0)
@@ -0,0 +1,108 @@
+// 2005-11-25 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.1.3 deque modifiers
+
+#include <deque>
+#include <testsuite_hooks.h>
+
+const int A[] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15};
+const int A0[] = {-5, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+const int A1[] = {-5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+const int A2[] = {-5, 0, 1, 2, 8, 9, 10, 11, 12, 13, 14, 15};
+const int A3[] = {-5, 0, 1, 2, 8, 9, 10, 11};
+const int A4[] = {2, 8, 9, 10, 11};
+const int A5[] = {2, 8, 10, 11};
+const int A6[] = {2, 8, 10};
+const int N = sizeof(A) / sizeof(int);
+const int N0 = sizeof(A0) / sizeof(int);
+const int N1 = sizeof(A1) / sizeof(int);
+const int N2 = sizeof(A2) / sizeof(int);
+const int N3 = sizeof(A3) / sizeof(int);
+const int N4 = sizeof(A4) / sizeof(int);
+const int N5 = sizeof(A5) / sizeof(int);
+const int N6 = sizeof(A6) / sizeof(int);
+
+template<int Size>
+ class My_class
+ {
+ double dummy[Size];
+ int data;
+
+ public:
+ My_class(int num)
+ : data(num) { }
+
+ operator int() const
+ { return data; }
+ };
+
+template<typename T>
+ void
+ test01()
+ {
+ bool test __attribute__((unused)) = true;
+
+ typedef std::deque<T> deque_type;
+ typedef typename deque_type::iterator iterator_type;
+
+ deque_type v(A, A + N);
+
+ iterator_type it0 = v.erase(v.begin() + 1, v.begin() + 4);
+ VERIFY( it0 == v.begin() + 1 );
+ VERIFY( std::equal(v.begin(), v.end(), A0) );
+
+ 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() + 8, v.end());
+ VERIFY( it3 == v.begin() + 8 );
+ VERIFY( std::equal(v.begin(), v.end(), A3) );
+
+ iterator_type it4 = v.erase(v.begin(), v.begin() + 3);
+ VERIFY( it4 == v.begin() );
+ VERIFY( std::equal(v.begin(), v.end(), A4) );
+
+ iterator_type it5 = v.erase(v.begin() + 2);
+ VERIFY( it5 == v.begin() + 2 );
+ VERIFY( std::equal(v.begin(), v.end(), A5) );
+
+ iterator_type it6 = v.erase(v.begin() + 3, v.end());
+ VERIFY( it6 == v.begin() + 3 );
+ VERIFY( std::equal(v.begin(), v.end(), A6) );
+
+ iterator_type it7 = v.erase(v.begin(), v.end());
+ VERIFY( it7 == v.begin() );
+ VERIFY( v.empty() );
+ }
+
+int main()
+{
+ test01<My_class<1> >();
+ test01<My_class<8> >();
+ test01<My_class<32> >();
+ return 0;
+}