From 6eef740212b6c2e5eb68d245ee5a2bda7f581841 Mon Sep 17 00:00:00 2001 From: Chris Jefferson Date: Mon, 5 Nov 2007 19:46:07 +0000 Subject: [PATCH] stl_vector.h (vector<>::push_back<>(_Args...), [...]): Add. 2007-11-05 Chris Jefferson Paolo Carlini * include/bits/stl_vector.h (vector<>::push_back<>(_Args...), emplace<>(iterator, _Args...), insert(iterator, _Tp&&), _M_insert_aux<>(iterator, _Args&&...)): Add. * include/bits/vector.tcc (insert(iterator, value_type&&), emplace<>(iterator, _Args...), _M_insert_aux<>(iterator, _Args&&...)): Define. (_M_fill_insert(iterator, size_type, const value_type&), _M_range_insert(iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag)): Use __uninitialized_move_a, _GLIBCXX_MOVE_BACKWARD3 when possible. * include/bits/stl_uninitialized.h (__uninitialized_move_a): Add. * include/debug/vector (vector<>::push_back<>(_Args...), emplace<>(iterator, _Args...), insert(iterator, _Tp&&)): Add. * testsuite/23_containers/vector/modifiers/moveable.cc: Enable. * testsuite/23_containers/vector/resize/moveable.cc: Likewise. * testsuite/23_containers/vector/cons/moveable.cc: Likewise. * testsuite/23_containers/vector/requirements/dr438/assign_neg.cc: Adjust dg-error line numbers. * testsuite/23_containers/vector/requirements/dr438/insert_neg.cc: Likewise. * testsuite/23_containers/vector/requirements/dr438/ constructor_1_neg.cc: Likewise. * testsuite/23_containers/vector/requirements/dr438/ constructor_2_neg.cc: Likewise. Co-Authored-By: Paolo Carlini From-SVN: r129907 --- libstdc++-v3/ChangeLog | 28 ++++++ libstdc++-v3/include/bits/stl_uninitialized.h | 11 +++ libstdc++-v3/include/bits/stl_vector.h | 56 +++++++++++ libstdc++-v3/include/bits/vector.tcc | 106 +++++++++++++++++---- libstdc++-v3/include/debug/vector | 50 ++++++++++ .../23_containers/vector/cons/moveable.cc | 1 - .../23_containers/vector/modifiers/moveable.cc | 1 - .../vector/requirements/dr438/assign_neg.cc | 2 +- .../vector/requirements/dr438/constructor_1_neg.cc | 2 +- .../vector/requirements/dr438/constructor_2_neg.cc | 2 +- .../vector/requirements/dr438/insert_neg.cc | 2 +- .../23_containers/vector/resize/moveable.cc | 1 - 12 files changed, 235 insertions(+), 27 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 9687899..36c9f4b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,31 @@ +2007-11-05 Chris Jefferson + Paolo Carlini + + * include/bits/stl_vector.h (vector<>::push_back<>(_Args...), + emplace<>(iterator, _Args...), insert(iterator, _Tp&&), + _M_insert_aux<>(iterator, _Args&&...)): Add. + * include/bits/vector.tcc (insert(iterator, value_type&&), + emplace<>(iterator, _Args...), _M_insert_aux<>(iterator, _Args&&...)): + Define. + (_M_fill_insert(iterator, size_type, const value_type&), + _M_range_insert(iterator, _ForwardIterator, _ForwardIterator, + std::forward_iterator_tag)): Use __uninitialized_move_a, + _GLIBCXX_MOVE_BACKWARD3 when possible. + * include/bits/stl_uninitialized.h (__uninitialized_move_a): Add. + * include/debug/vector (vector<>::push_back<>(_Args...), + emplace<>(iterator, _Args...), insert(iterator, _Tp&&)): Add. + * testsuite/23_containers/vector/modifiers/moveable.cc: Enable. + * testsuite/23_containers/vector/resize/moveable.cc: Likewise. + * testsuite/23_containers/vector/cons/moveable.cc: Likewise. + * testsuite/23_containers/vector/requirements/dr438/assign_neg.cc: + Adjust dg-error line numbers. + * testsuite/23_containers/vector/requirements/dr438/insert_neg.cc: + Likewise. + * testsuite/23_containers/vector/requirements/dr438/ + constructor_1_neg.cc: Likewise. + * testsuite/23_containers/vector/requirements/dr438/ + constructor_2_neg.cc: Likewise. + 2007-11-03 Paolo Carlini Kai-Uwe Bux diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index d3e7a2c8..6f7437aa 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -261,6 +261,17 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _ForwardIterator __result, allocator<_Tp>&) { return std::uninitialized_copy(__first, __last, __result); } + template + inline _ForwardIterator + __uninitialized_move_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + { + return std::__uninitialized_copy_a(_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), + __result, __alloc); + } + template void __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index f48fbdb..bf2cc27 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -683,6 +683,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) * done in constant time if the %vector has preallocated space * available. */ +#ifndef __GXX_EXPERIMENTAL_CXX0X__ void push_back(const value_type& __x) { @@ -694,6 +695,21 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) else _M_insert_aux(end(), __x); } +#else + template + void + push_back(_Args&&... __args) + { + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + { + this->_M_impl.construct(this->_M_impl._M_finish, + std::forward<_Args>(__args)...); + ++this->_M_impl._M_finish; + } + else + _M_insert_aux(end(), std::forward<_Args>(__args)...); + } +#endif /** * @brief Removes last element. @@ -711,6 +727,24 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) this->_M_impl.destroy(this->_M_impl._M_finish); } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + /** + * @brief Inserts an object in %vector before specified iterator. + * @param position An iterator into the %vector. + * @param args Arguments. + * @return An iterator that points to the inserted data. + * + * This function will insert an object of type T constructed + * with T(std::forward(args)...) before the specified location. + * Note that this kind of operation could be expensive for a %vector + * and if it is frequently used the user should consider using + * std::list. + */ + template + iterator + emplace(iterator __position, _Args&&... __args); +#endif + /** * @brief Inserts given value into %vector before specified iterator. * @param position An iterator into the %vector. @@ -725,6 +759,22 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) iterator insert(iterator __position, const value_type& __x); +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + /** + * @brief Inserts given rvalue into %vector before specified iterator. + * @param position An iterator into the %vector. + * @param x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given rvalue before + * the specified location. Note that this kind of operation + * could be expensive for a %vector and if it is frequently + * used the user should consider using std::list. + */ + iterator + insert(iterator __position, value_type&& __x); +#endif + /** * @brief Inserts a number of copies of given data into the %vector. * @param position An iterator into the %vector. @@ -1014,8 +1064,14 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); // Called by insert(p,x) +#ifndef __GXX_EXPERIMENTAL_CXX0X__ void _M_insert_aux(iterator __position, const value_type& __x); +#else + template + void + _M_insert_aux(iterator __position, _Args&&... __args); +#endif // Called by the latter. size_type diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index e15d80d..b097f44 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -105,6 +105,26 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) return iterator(this->_M_impl._M_start + __n); } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template + typename vector<_Tp, _Alloc>::iterator + vector<_Tp, _Alloc>:: + insert(iterator __position, value_type&& __x) + { + const size_type __n = __position - begin(); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage + && __position == end()) + { + this->_M_impl.construct(this->_M_impl._M_finish, + std::forward(__x)); + ++this->_M_impl._M_finish; + } + else + _M_insert_aux(__position, std::forward(__x)); + return iterator(this->_M_impl._M_start + __n); + } +#endif + template typename vector<_Tp, _Alloc>::iterator vector<_Tp, _Alloc>:: @@ -241,21 +261,53 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) } } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template + template + typename vector<_Tp, _Alloc>::iterator + vector<_Tp, _Alloc>:: + emplace(iterator __position, _Args&&... __args) + { + const size_type __n = __position - begin(); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage + && __position == end()) + { + this->_M_impl.construct(this->_M_impl._M_finish, + std::forward<_Args>(__args)...); + ++this->_M_impl._M_finish; + } + else + _M_insert_aux(__position, std::forward<_Args>(__args)...); + return iterator(this->_M_impl._M_start + __n); + } + + template + template + void + vector<_Tp, _Alloc>:: + _M_insert_aux(iterator __position, _Args&&... __args) + { + _Tp __x_copy(std::forward<_Args>(__args)...); +#else template void vector<_Tp, _Alloc>:: _M_insert_aux(iterator __position, const _Tp& __x) { +#endif if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) { this->_M_impl.construct(this->_M_impl._M_finish, - *(this->_M_impl._M_finish - 1)); + _GLIBCXX_MOVE(*(this->_M_impl._M_finish + - 1))); ++this->_M_impl._M_finish; +#ifndef __GXX_EXPERIMENTAL_CXX0X__ _Tp __x_copy = __x; - std::copy_backward(__position.base(), - this->_M_impl._M_finish - 2, - this->_M_impl._M_finish - 1); - *__position = __x_copy; +#endif + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + this->_M_impl._M_finish - 2, + this->_M_impl._M_finish - 1); + *__position = _GLIBCXX_MOVE(__x_copy); } else { @@ -266,13 +318,17 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) try { __new_finish = - std::__uninitialized_copy_a(this->_M_impl._M_start, + std::__uninitialized_move_a(this->_M_impl._M_start, __position.base(), __new_start, _M_get_Tp_allocator()); +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + this->_M_impl.construct(__new_finish, std::move(__x_copy)); +#else this->_M_impl.construct(__new_finish, __x); +#endif ++__new_finish; __new_finish = - std::__uninitialized_copy_a(__position.base(), + std::__uninitialized_move_a(__position.base(), this->_M_impl._M_finish, __new_finish, _M_get_Tp_allocator()); @@ -301,21 +357,26 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) { if (__n != 0) { +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + value_type __x_copy = __x; +#endif if (size_type(this->_M_impl._M_end_of_storage - this->_M_impl._M_finish) >= __n) { +#ifndef __GXX_EXPERIMENTAL_CXX0X__ value_type __x_copy = __x; +#endif const size_type __elems_after = end() - __position; pointer __old_finish(this->_M_impl._M_finish); if (__elems_after > __n) { - std::__uninitialized_copy_a(this->_M_impl._M_finish - __n, + std::__uninitialized_move_a(this->_M_impl._M_finish - __n, this->_M_impl._M_finish, this->_M_impl._M_finish, _M_get_Tp_allocator()); this->_M_impl._M_finish += __n; - std::copy_backward(__position.base(), __old_finish - __n, - __old_finish); + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + __old_finish - __n, __old_finish); std::fill(__position.base(), __position.base() + __n, __x_copy); } @@ -326,7 +387,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) __x_copy, _M_get_Tp_allocator()); this->_M_impl._M_finish += __n - __elems_after; - std::__uninitialized_copy_a(__position.base(), __old_finish, + std::__uninitialized_move_a(__position.base(), __old_finish, this->_M_impl._M_finish, _M_get_Tp_allocator()); this->_M_impl._M_finish += __elems_after; @@ -342,15 +403,19 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) try { __new_finish = - std::__uninitialized_copy_a(this->_M_impl._M_start, + std::__uninitialized_move_a(this->_M_impl._M_start, __position.base(), __new_start, _M_get_Tp_allocator()); +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + std::__uninitialized_fill_n_a(__new_finish, __n, __x_copy, +#else std::__uninitialized_fill_n_a(__new_finish, __n, __x, +#endif _M_get_Tp_allocator()); __new_finish += __n; __new_finish = - std::__uninitialized_copy_a(__position.base(), + std::__uninitialized_move_a(__position.base(), this->_M_impl._M_finish, __new_finish, _M_get_Tp_allocator()); @@ -405,13 +470,13 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) pointer __old_finish(this->_M_impl._M_finish); if (__elems_after > __n) { - std::__uninitialized_copy_a(this->_M_impl._M_finish - __n, + std::__uninitialized_move_a(this->_M_impl._M_finish - __n, this->_M_impl._M_finish, this->_M_impl._M_finish, _M_get_Tp_allocator()); this->_M_impl._M_finish += __n; - std::copy_backward(__position.base(), __old_finish - __n, - __old_finish); + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + __old_finish - __n, __old_finish); std::copy(__first, __last, __position); } else @@ -422,7 +487,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) this->_M_impl._M_finish, _M_get_Tp_allocator()); this->_M_impl._M_finish += __n - __elems_after; - std::__uninitialized_copy_a(__position.base(), + std::__uninitialized_move_a(__position.base(), __old_finish, this->_M_impl._M_finish, _M_get_Tp_allocator()); @@ -439,15 +504,16 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) try { __new_finish = - std::__uninitialized_copy_a(this->_M_impl._M_start, + std::__uninitialized_move_a(this->_M_impl._M_start, __position.base(), __new_start, _M_get_Tp_allocator()); __new_finish = - std::__uninitialized_copy_a(__first, __last, __new_finish, + std::__uninitialized_copy_a(__first, __last, + __new_finish, _M_get_Tp_allocator()); __new_finish = - std::__uninitialized_copy_a(__position.base(), + std::__uninitialized_move_a(__position.base(), this->_M_impl._M_finish, __new_finish, _M_get_Tp_allocator()); diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector index ce44241..977fbbd 100644 --- a/libstdc++-v3/include/debug/vector +++ b/libstdc++-v3/include/debug/vector @@ -278,6 +278,7 @@ namespace __debug using _Base::data; // 23.2.4.3 modifiers: +#ifndef __GXX_EXPERIMENTAL_CXX0X__ void push_back(const _Tp& __x) { @@ -287,6 +288,18 @@ namespace __debug this->_M_invalidate_all(); _M_update_guaranteed_capacity(); } +#else + template + void + push_back(_Args... __args) + { + bool __realloc = _M_requires_reallocation(this->size() + 1); + _Base::push_back(std::forward<_Args>(__args)...); + if (__realloc) + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + } +#endif void pop_back() @@ -297,6 +310,25 @@ namespace __debug _Base::pop_back(); } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template + iterator + emplace(iterator __position, _Args... __args) + { + __glibcxx_check_insert(__position); + bool __realloc = _M_requires_reallocation(this->size() + 1); + difference_type __offset = __position - begin(); + typename _Base::iterator __res = _Base::emplace(__position.base(), + std::forward<_Args>(__args)...); + if (__realloc) + this->_M_invalidate_all(); + else + this->_M_invalidate_if(_After_nth(__offset, _M_base().begin())); + _M_update_guaranteed_capacity(); + return iterator(__res, this); + } +#endif + iterator insert(iterator __position, const _Tp& __x) { @@ -312,6 +344,24 @@ namespace __debug return iterator(__res, this); } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + insert(iterator __position, _Tp&& __x) + { + __glibcxx_check_insert(__position); + bool __realloc = _M_requires_reallocation(this->size() + 1); + difference_type __offset = __position - begin(); + typename _Base::iterator __res = _Base::insert(__position.base(), + std::forward<_Tp>(__x)); + if (__realloc) + this->_M_invalidate_all(); + else + this->_M_invalidate_if(_After_nth(__offset, _M_base().begin())); + _M_update_guaranteed_capacity(); + return iterator(__res, this); + } +#endif + void insert(iterator __position, size_type __n, const _Tp& __x) { diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/moveable.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/moveable.cc index 7184a25..688423e 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/cons/moveable.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/moveable.cc @@ -1,5 +1,4 @@ // { dg-do compile } -// { dg-require-rvalref "" } // { dg-options "-std=gnu++0x" } // Copyright (C) 2005, 2007 Free Software Foundation, Inc. diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc index ef4410a..15adafc 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc @@ -1,4 +1,3 @@ -// { dg-require-rvalref "" } // { dg-options "-std=gnu++0x" } // Copyright (C) 2005, 2007 Free Software Foundation, Inc. diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc index c5b20cb..6e7d587 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc @@ -19,7 +19,7 @@ // USA. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 945 } +// { dg-error "no matching" "" { target *-*-* } 995 } // { dg-excess-errors "" } #include diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc index 28e0c4d..532d89a 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc @@ -19,7 +19,7 @@ // USA. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 885 } +// { dg-error "no matching" "" { target *-*-* } 935 } // { dg-excess-errors "" } #include diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc index 717bbc6..640aa79 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc @@ -19,7 +19,7 @@ // USA. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 885 } +// { dg-error "no matching" "" { target *-*-* } 935 } // { dg-excess-errors "" } #include diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc index 62b331a..1971317 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc @@ -19,7 +19,7 @@ // USA. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 986 } +// { dg-error "no matching" "" { target *-*-* } 1036 } // { dg-excess-errors "" } #include diff --git a/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc b/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc index 84136f4..f4dbc19 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc @@ -1,4 +1,3 @@ -// { dg-require-rvalref "" } // { dg-options "-std=gnu++0x" } // Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. -- 2.7.4