From: François Dumont Date: Mon, 11 Jul 2016 20:17:56 +0000 (+0000) Subject: stl_vector.h (push_back(const value_type&)): Forward to _M_realloc_insert. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=76225d2ca77038233f5af5903ab0bd10aa78e611;p=gcc.git stl_vector.h (push_back(const value_type&)): Forward to _M_realloc_insert. 2016-07-11 François Dumont * include/bits/stl_vector.h (push_back(const value_type&)): Forward to _M_realloc_insert. (insert(const_iterator, value_type&&)): Forward to _M_insert_rval. (_M_realloc_insert): Declare new function. (_M_emplace_back_aux): Remove definition. * include/bits/vector.tcc (emplace_back(_Args...)): Use _M_realloc_insert. (insert(const_iterator, const value_type&)): Likewise. (_M_insert_rval, _M_emplace_aux): Likewise. (_M_emplace_back_aux): Remove declaration. (_M_realloc_insert): Define. * testsuite/23_containers/vector/modifiers/insert_vs_emplace.cc: Adjust expected results for emplacing an lvalue with reallocation. From-SVN: r238226 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0aee6800828..1d0abe1c242 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,19 @@ +2016-07-11 François Dumont + + * include/bits/stl_vector.h (push_back(const value_type&)): Forward + to _M_realloc_insert. + (insert(const_iterator, value_type&&)): Forward to _M_insert_rval. + (_M_realloc_insert): Declare new function. + (_M_emplace_back_aux): Remove definition. + * include/bits/vector.tcc (emplace_back(_Args...)): + Use _M_realloc_insert. + (insert(const_iterator, const value_type&)): Likewise. + (_M_insert_rval, _M_emplace_aux): Likewise. + (_M_emplace_back_aux): Remove declaration. + (_M_realloc_insert): Define. + * testsuite/23_containers/vector/modifiers/insert_vs_emplace.cc: + Adjust expected results for emplacing an lvalue with reallocation. + 2016-07-10 Ville Voutilainen Implement std::optional. diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 8e8aa7cf0d1..85abf4a3cc0 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -946,11 +946,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ++this->_M_impl._M_finish; } else -#if __cplusplus >= 201103L - _M_emplace_back_aux(__x); -#else - _M_insert_aux(end(), __x); -#endif + _M_realloc_insert(end(), __x); } #if __cplusplus >= 201103L @@ -1436,6 +1432,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by insert(p,x) void _M_insert_aux(iterator __position, const value_type& __x); + + void + _M_realloc_insert(iterator __position, const value_type& __x); #else // A value_type object constructed with _Alloc_traits::construct() // and destroyed with _Alloc_traits::destroy(). @@ -1469,16 +1468,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_insert_aux(iterator __position, _Arg&& __arg); + template + void + _M_realloc_insert(iterator __position, _Args&&... __args); + // Either move-construct at the end, or forward to _M_insert_aux. iterator _M_insert_rval(const_iterator __position, value_type&& __v); - // Called by push_back(x) and emplace_back(args) when they need to - // reallocate. - template - void - _M_emplace_back_aux(_Args&&... __args); - // Try to emplace at the end, otherwise forward to _M_insert_aux. template iterator diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index dd0d288eaab..9717b74a978 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -98,7 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ++this->_M_impl._M_finish; } else - _M_emplace_back_aux(std::forward<_Args>(__args)...); + _M_realloc_insert(end(), std::forward<_Args>(__args)...); } #endif @@ -112,29 +112,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif { const size_type __n = __position - begin(); - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage - && __position == end()) - { - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x); - ++this->_M_impl._M_finish; - } - else - { + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == end()) + { + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + __x); + ++this->_M_impl._M_finish; + } + else + { #if __cplusplus >= 201103L - const auto __pos = begin() + (__position - cbegin()); - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) - { - // __x could be an existing element of this vector, so make a - // copy of it before _M_insert_aux moves elements around. - _Temporary_value __x_copy(this, __x); - _M_insert_aux(__pos, std::move(__x_copy._M_val())); - } - else - _M_insert_aux(__pos, __x); + const auto __pos = begin() + (__position - cbegin()); + // __x could be an existing element of this vector, so make a + // copy of it before _M_insert_aux moves elements around. + _Temporary_value __x_copy(this, __x); + _M_insert_aux(__pos, std::move(__x_copy._M_val())); #else _M_insert_aux(__position, __x); #endif - } + } + else +#if __cplusplus >= 201103L + _M_realloc_insert(begin() + (__position - cbegin()), __x); +#else + _M_realloc_insert(__position, __x); +#endif + return iterator(this->_M_impl._M_start + __n); } @@ -304,15 +307,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_insert_rval(const_iterator __position, value_type&& __v) -> iterator { const auto __n = __position - cbegin(); - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage - && __position == cend()) - { - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - std::move(__v)); - ++this->_M_impl._M_finish; - } + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == cend()) + { + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + std::move(__v)); + ++this->_M_impl._M_finish; + } + else + _M_insert_aux(begin() + __n, std::move(__v)); else - _M_insert_aux(begin() + __n, std::move(__v)); + _M_realloc_insert(begin() + __n, std::move(__v)); + return iterator(this->_M_impl._M_start + __n); } @@ -324,16 +330,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER -> iterator { const auto __n = __position - cbegin(); - if (__position == cend()) - emplace_back(std::forward<_Args>(__args)...); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == cend()) + { + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + std::forward<_Args>(__args)...); + ++this->_M_impl._M_finish; + } + else + { + // We need to construct a temporary because something in __args... + // could alias one of the elements of the container and so we + // need to use it before _M_insert_aux moves elements around. + _Temporary_value __tmp(this, std::forward<_Args>(__args)...); + _M_insert_aux(begin() + __n, std::move(__tmp._M_val())); + } else - { - // We need to construct a temporary because something in __args... - // could alias one of the elements of the container and so we - // need to use it before _M_insert_aux moves elements around. - _Temporary_value __tmp(this, std::forward<_Args>(__args)...); - _M_insert_aux(begin() + __n, std::move(__tmp._M_val())); - } + _M_realloc_insert(begin() + __n, std::forward<_Args>(__args)...); + return iterator(this->_M_impl._M_start + __n); } @@ -349,78 +363,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_insert_aux(iterator __position, const _Tp& __x) #endif { - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) - { - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - _GLIBCXX_MOVE(*(this->_M_impl._M_finish - - 1))); - ++this->_M_impl._M_finish; + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + _GLIBCXX_MOVE(*(this->_M_impl._M_finish + - 1))); + ++this->_M_impl._M_finish; #if __cplusplus < 201103L - _Tp __x_copy = __x; + _Tp __x_copy = __x; #endif - _GLIBCXX_MOVE_BACKWARD3(__position.base(), - this->_M_impl._M_finish - 2, - this->_M_impl._M_finish - 1); + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + this->_M_impl._M_finish - 2, + this->_M_impl._M_finish - 1); #if __cplusplus < 201103L - *__position = __x_copy; -#else - *__position = std::forward<_Arg>(__arg); -#endif - } - else - { - const size_type __len = - _M_check_len(size_type(1), "vector::_M_insert_aux"); - const size_type __elems_before = __position - begin(); - pointer __new_start(this->_M_allocate(__len)); - pointer __new_finish(__new_start); - __try - { - // The order of the three operations is dictated by the C++11 - // case, where the moves could alter a new element belonging - // to the existing vector. This is an issue only for callers - // taking the element by lvalue ref (see last bullet of C++11 - // [res.on.arguments]). - _Alloc_traits::construct(this->_M_impl, - __new_start + __elems_before, -#if __cplusplus >= 201103L - std::forward<_Arg>(__arg)); + *__position = __x_copy; #else - __x); + *__position = std::forward<_Arg>(__arg); #endif - __new_finish = pointer(); - - __new_finish - = std::__uninitialized_move_if_noexcept_a - (this->_M_impl._M_start, __position.base(), - __new_start, _M_get_Tp_allocator()); - - ++__new_finish; - - __new_finish - = std::__uninitialized_move_if_noexcept_a - (__position.base(), this->_M_impl._M_finish, - __new_finish, _M_get_Tp_allocator()); - } - __catch(...) - { - if (!__new_finish) - _Alloc_traits::destroy(this->_M_impl, - __new_start + __elems_before); - else - std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); - _M_deallocate(__new_start, __len); - __throw_exception_again; - } - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = __new_start; - this->_M_impl._M_finish = __new_finish; - this->_M_impl._M_end_of_storage = __new_start + __len; - } } #if __cplusplus >= 201103L @@ -428,44 +385,66 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template void vector<_Tp, _Alloc>:: - _M_emplace_back_aux(_Args&&... __args) - { - const size_type __len = - _M_check_len(size_type(1), "vector::_M_emplace_back_aux"); - pointer __new_start(this->_M_allocate(__len)); - pointer __new_finish(__new_start); - __try - { - _Alloc_traits::construct(this->_M_impl, __new_start + size(), - std::forward<_Args>(__args)...); - __new_finish = pointer(); + _M_realloc_insert(iterator __position, _Args&&... __args) +#else + template + void + vector<_Tp, _Alloc>:: + _M_realloc_insert(iterator __position, const _Tp& __x) +#endif + { + const size_type __len = + _M_check_len(size_type(1), "vector::_M_realloc_insert"); + const size_type __elems_before = __position - begin(); + pointer __new_start(this->_M_allocate(__len)); + pointer __new_finish(__new_start); + __try + { + // The order of the three operations is dictated by the C++11 + // case, where the moves could alter a new element belonging + // to the existing vector. This is an issue only for callers + // taking the element by lvalue ref (see last bullet of C++11 + // [res.on.arguments]). + _Alloc_traits::construct(this->_M_impl, + __new_start + __elems_before, +#if __cplusplus >= 201103L + std::forward<_Args>(__args)...); +#else + __x); +#endif + __new_finish = pointer(); - __new_finish - = std::__uninitialized_move_if_noexcept_a - (this->_M_impl._M_start, this->_M_impl._M_finish, - __new_start, _M_get_Tp_allocator()); + __new_finish + = std::__uninitialized_move_if_noexcept_a + (this->_M_impl._M_start, __position.base(), + __new_start, _M_get_Tp_allocator()); - ++__new_finish; - } - __catch(...) - { - if (!__new_finish) - _Alloc_traits::destroy(this->_M_impl, __new_start + size()); - else - std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); - _M_deallocate(__new_start, __len); - __throw_exception_again; - } - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = __new_start; - this->_M_impl._M_finish = __new_finish; - this->_M_impl._M_end_of_storage = __new_start + __len; - } -#endif + ++__new_finish; + + __new_finish + = std::__uninitialized_move_if_noexcept_a + (__position.base(), this->_M_impl._M_finish, + __new_finish, _M_get_Tp_allocator()); + } + __catch(...) + { + if (!__new_finish) + _Alloc_traits::destroy(this->_M_impl, + __new_start + __elems_before); + else + std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_finish; + this->_M_impl._M_end_of_storage = __new_start + __len; + } template void @@ -520,7 +499,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER pointer __new_finish(__new_start); __try { - // See _M_insert_aux above. + // See _M_realloc_insert above. std::__uninitialized_fill_n_a(__new_start + __elems_before, __n, __x, _M_get_Tp_allocator()); diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert_vs_emplace.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert_vs_emplace.cc index 1b461240592..39a3f031b46 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert_vs_emplace.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert_vs_emplace.cc @@ -223,8 +223,7 @@ test03() void test04() { - const X::special expected_ins{ 0, 3, 1, 0, 3, 0 }; - const X::special expected_emp{ 0, 4, 1, 0, 4, 0 }; + const X::special expected{ 0, 3, 1, 0, 3, 0 }; X::special ins, emp; { std::vector v; @@ -254,8 +253,8 @@ test04() // std::cout << "----\n"; emp = X::sp; } - VERIFY( ins == expected_ins ); - VERIFY( emp == expected_emp ); + VERIFY( ins == emp ); + VERIFY( ins == expected ); } // insert vs emplace xvalue reallocation