diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 273e2f1a15c..2599c135ec5 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,25 @@ +2005-12-17 Paolo Carlini + + * include/bits/stl_vector.h (vector(const vector&)): Use + _M_get_Tp_allocator. + * include/bits/stl_deque.h (deque(const deque&)): Likewise. + (_M_destroy_data): Adjust. + +2005-12-17 Paolo Carlini + + * 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 copy unnecessarily. + (_M_destroy_data_aux): Define. + * testsuite/23_containers/deque/modifiers/erase/1.cc: New. + * testsuite/23_containers/deque/modifiers/erase/2.cc: Likewise. + 2005-12-17 Gabriel Dos Reis * include/bits/valarray_after.h (_Expr<>::operator[](slice)): diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc index 71722238964..d8f5ef6f0d2 100644 --- a/libstdc++-v3/include/bits/deque.tcc +++ b/libstdc++-v3/include/bits/deque.tcc @@ -72,8 +72,8 @@ namespace _GLIBCXX_STD 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 @@ namespace _GLIBCXX_STD { 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::copy_backward(this->_M_impl._M_start, __position, __next); + if (__position != begin()) + std::copy_backward(begin(), __position, __next); pop_front(); } else { - std::copy(__next, this->_M_impl._M_finish, __position); + if (__next != end()) + std::copy(__next, end(), __position); pop_back(); } - return this->_M_impl._M_start + __index; + return begin() + __index; } template @@ -131,73 +133,31 @@ namespace _GLIBCXX_STD 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(__elems_before) < (size() - __n) / 2) { - std::copy_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::copy_backward(begin(), __first, __last); + _M_erase_at_begin(begin() + __n); } else { - std::copy(__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::copy(__last, end(), __first); + _M_erase_at_end(end() - __n); } - return this->_M_impl._M_start + __elems_before; + return begin() + __elems_before; } } - template - 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 template void @@ -209,7 +169,7 @@ namespace _GLIBCXX_STD 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); } @@ -673,6 +633,28 @@ namespace _GLIBCXX_STD } } + template + 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 void deque<_Tp, _Alloc>:: diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index eb534ca8c94..15401ba6865 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -687,7 +687,7 @@ namespace _GLIBCXX_STD * by @a x. */ deque(const deque& __x) - : _Base(__x.get_allocator(), __x.size()) + : _Base(__x._M_get_Tp_allocator(), __x.size()) { std::__uninitialized_copy_a(__x.begin(), __x.end(), this->_M_impl._M_start, _M_get_Tp_allocator()); } @@ -722,8 +722,7 @@ namespace _GLIBCXX_STD * 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. @@ -833,7 +832,8 @@ namespace _GLIBCXX_STD * in reverse element order. */ reverse_iterator - rend() { return reverse_iterator(this->_M_impl._M_start); } + rend() + { return reverse_iterator(this->_M_impl._M_start); } /** * Returns a read-only (constant) reverse iterator that points @@ -871,7 +871,7 @@ namespace _GLIBCXX_STD { 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); } @@ -1191,7 +1191,9 @@ namespace _GLIBCXX_STD * 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. @@ -1301,7 +1303,7 @@ namespace _GLIBCXX_STD 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 @@ -1316,7 +1318,7 @@ namespace _GLIBCXX_STD } else { - erase(begin() + __n, end()); + _M_erase_at_end(begin() + __n); std::fill(begin(), end(), __val); } } @@ -1328,8 +1330,11 @@ namespace _GLIBCXX_STD * @endif */ void _M_push_back_aux(const value_type&); + void _M_push_front_aux(const value_type&); + void _M_pop_back_aux(); + void _M_pop_front_aux(); //@} @@ -1391,6 +1396,55 @@ namespace _GLIBCXX_STD _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 + void + _M_destroy_data(iterator __first, iterator __last, const _Alloc1&) + { _M_destroy_data_aux(__first, __last); } + + void + _M_destroy_data(iterator __first, iterator __last, + const std::allocator<_Tp>&) + { + typedef typename std::__is_scalar::__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 diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index d8ea4b37047..731806b0a94 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -230,7 +230,7 @@ namespace _GLIBCXX_STD * @a x (for fast expansion) will not be copied. */ vector(const vector& __x) - : _Base(__x.size(), __x.get_allocator()) + : _Base(__x.size(), __x._M_get_Tp_allocator()) { this->_M_impl._M_finish = std::__uninitialized_copy_a(__x.begin(), __x.end(), this->_M_impl._M_start, diff --git a/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/1.cc b/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/1.cc new file mode 100644 index 00000000000..167f1f2a12b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/1.cc @@ -0,0 +1,136 @@ +// 2005-11-25 Paolo Carlini + +// 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 +#include + +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(A5) / sizeof(int); + +void +test01() +{ + bool test __attribute__((unused)) = true; + + typedef std::deque 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( v.size() == N1 ); + 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( v.size() == N2 ); + VERIFY( std::equal(v.begin(), v.end(), A2) ); + + iterator_type it3 = v.erase(v.begin() + 6, v.end()); + VERIFY( it3 == v.begin() + 6 ); + VERIFY( v.size() == N3 ); + VERIFY( std::equal(v.begin(), v.end(), A3) ); + + iterator_type it4 = v.erase(v.begin(), v.begin() + 3); + VERIFY( it4 == v.begin() ); + VERIFY( v.size() == N4 ); + VERIFY( std::equal(v.begin(), v.end(), A4) ); + + iterator_type it5 = v.erase(v.begin() + 2); + VERIFY( it5 == v.begin() + 2 ); + VERIFY( v.size() == N5 ); + 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 > 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(1, A[i])); + for (int i = 0; i < N1; ++i) + v1.push_back(std::deque(1, A1[i])); + for (int i = 0; i < N2; ++i) + v2.push_back(std::deque(1, A2[i])); + for (int i = 0; i < N3; ++i) + v3.push_back(std::deque(1, A3[i])); + for (int i = 0; i < N4; ++i) + v4.push_back(std::deque(1, A4[i])); + for (int i = 0; i < N5; ++i) + v5.push_back(std::deque(1, A5[i])); + + iterator_type it1 = v.erase(v.begin() + 1); + VERIFY( it1 == v.begin() + 1 ); + VERIFY( v.size() == N1 ); + 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( v.size() == N2 ); + 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( v.size() == N3 ); + VERIFY( std::equal(v.begin(), v.end(), v3.begin()) ); + + iterator_type it4 = v.erase(v.begin(), v.begin() + 3); + VERIFY( it4 == v.begin() ); + VERIFY( v.size() == N4 ); + VERIFY( std::equal(v.begin(), v.end(), v4.begin()) ); + + iterator_type it5 = v.erase(v.begin() + 2); + VERIFY( it5 == v.begin() + 2 ); + VERIFY( v.size() == N5 ); + 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; +} diff --git a/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/2.cc b/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/2.cc new file mode 100644 index 00000000000..19542d3999e --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/2.cc @@ -0,0 +1,115 @@ +// 2005-11-25 Paolo Carlini + +// 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 +#include + +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 + class My_class + { + double dummy[Size]; + int data; + + public: + My_class(int num) + : data(num) { } + + operator int() const + { return data; } + }; + +template + void + test01() + { + bool test __attribute__((unused)) = true; + + typedef std::deque 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( v.size() == N0 ); + VERIFY( std::equal(v.begin(), v.end(), A0) ); + + iterator_type it1 = v.erase(v.begin() + 1); + VERIFY( it1 == v.begin() + 1 ); + VERIFY( v.size() == N1 ); + 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( v.size() == N2 ); + VERIFY( std::equal(v.begin(), v.end(), A2) ); + + iterator_type it3 = v.erase(v.begin() + 8, v.end()); + VERIFY( it3 == v.begin() + 8 ); + VERIFY( v.size() == N3 ); + VERIFY( std::equal(v.begin(), v.end(), A3) ); + + iterator_type it4 = v.erase(v.begin(), v.begin() + 3); + VERIFY( it4 == v.begin() ); + VERIFY( v.size() == N4 ); + VERIFY( std::equal(v.begin(), v.end(), A4) ); + + iterator_type it5 = v.erase(v.begin() + 2); + VERIFY( it5 == v.begin() + 2 ); + VERIFY( v.size() == N5 ); + VERIFY( std::equal(v.begin(), v.end(), A5) ); + + iterator_type it6 = v.erase(v.begin() + 3, v.end()); + VERIFY( it6 == v.begin() + 3 ); + VERIFY( v.size() == N6 ); + 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 >(); + test01 >(); + test01 >(); + return 0; +}