Commit 76225d2c by François Dumont

stl_vector.h (push_back(const value_type&)): Forward to _M_realloc_insert.

2016-07-11  François Dumont  <fdumont@gcc.gnu.org>

	* 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
parent 4368a420
2016-07-11 François Dumont <fdumont@gcc.gnu.org>
* 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 <ville.voutilainen@gmail.com> 2016-07-10 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement std::optional. Implement std::optional.
......
...@@ -946,11 +946,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -946,11 +946,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
++this->_M_impl._M_finish; ++this->_M_impl._M_finish;
} }
else else
#if __cplusplus >= 201103L _M_realloc_insert(end(), __x);
_M_emplace_back_aux(__x);
#else
_M_insert_aux(end(), __x);
#endif
} }
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
...@@ -1436,6 +1432,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -1436,6 +1432,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Called by insert(p,x) // Called by insert(p,x)
void void
_M_insert_aux(iterator __position, const value_type& __x); _M_insert_aux(iterator __position, const value_type& __x);
void
_M_realloc_insert(iterator __position, const value_type& __x);
#else #else
// A value_type object constructed with _Alloc_traits::construct() // A value_type object constructed with _Alloc_traits::construct()
// and destroyed with _Alloc_traits::destroy(). // and destroyed with _Alloc_traits::destroy().
...@@ -1469,16 +1468,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -1469,16 +1468,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void void
_M_insert_aux(iterator __position, _Arg&& __arg); _M_insert_aux(iterator __position, _Arg&& __arg);
template<typename... _Args>
void
_M_realloc_insert(iterator __position, _Args&&... __args);
// Either move-construct at the end, or forward to _M_insert_aux. // Either move-construct at the end, or forward to _M_insert_aux.
iterator iterator
_M_insert_rval(const_iterator __position, value_type&& __v); _M_insert_rval(const_iterator __position, value_type&& __v);
// Called by push_back(x) and emplace_back(args) when they need to
// reallocate.
template<typename... _Args>
void
_M_emplace_back_aux(_Args&&... __args);
// Try to emplace at the end, otherwise forward to _M_insert_aux. // Try to emplace at the end, otherwise forward to _M_insert_aux.
template<typename... _Args> template<typename... _Args>
iterator iterator
......
...@@ -98,7 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -98,7 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
++this->_M_impl._M_finish; ++this->_M_impl._M_finish;
} }
else else
_M_emplace_back_aux(std::forward<_Args>(__args)...); _M_realloc_insert(end(), std::forward<_Args>(__args)...);
} }
#endif #endif
...@@ -112,29 +112,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -112,29 +112,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif #endif
{ {
const size_type __n = __position - begin(); const size_type __n = __position - begin();
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
&& __position == end()) if (__position == end())
{ {
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x); _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
++this->_M_impl._M_finish; __x);
} ++this->_M_impl._M_finish;
else }
{ else
{
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
const auto __pos = begin() + (__position - cbegin()); 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.
// __x could be an existing element of this vector, so make a _Temporary_value __x_copy(this, __x);
// copy of it before _M_insert_aux moves elements around. _M_insert_aux(__pos, std::move(__x_copy._M_val()));
_Temporary_value __x_copy(this, __x);
_M_insert_aux(__pos, std::move(__x_copy._M_val()));
}
else
_M_insert_aux(__pos, __x);
#else #else
_M_insert_aux(__position, __x); _M_insert_aux(__position, __x);
#endif #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); return iterator(this->_M_impl._M_start + __n);
} }
...@@ -304,15 +307,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -304,15 +307,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_insert_rval(const_iterator __position, value_type&& __v) -> iterator _M_insert_rval(const_iterator __position, value_type&& __v) -> iterator
{ {
const auto __n = __position - cbegin(); const auto __n = __position - cbegin();
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
&& __position == cend()) if (__position == cend())
{ {
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
std::move(__v)); std::move(__v));
++this->_M_impl._M_finish; ++this->_M_impl._M_finish;
} }
else
_M_insert_aux(begin() + __n, std::move(__v));
else 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); return iterator(this->_M_impl._M_start + __n);
} }
...@@ -324,16 +330,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -324,16 +330,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
-> iterator -> iterator
{ {
const auto __n = __position - cbegin(); const auto __n = __position - cbegin();
if (__position == cend()) if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
emplace_back(std::forward<_Args>(__args)...); 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 else
{ _M_realloc_insert(begin() + __n, std::forward<_Args>(__args)...);
// 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()));
}
return iterator(this->_M_impl._M_start + __n); return iterator(this->_M_impl._M_start + __n);
} }
...@@ -349,78 +363,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -349,78 +363,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_insert_aux(iterator __position, const _Tp& __x) _M_insert_aux(iterator __position, const _Tp& __x)
#endif #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
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - 1)));
_GLIBCXX_MOVE(*(this->_M_impl._M_finish ++this->_M_impl._M_finish;
- 1)));
++this->_M_impl._M_finish;
#if __cplusplus < 201103L #if __cplusplus < 201103L
_Tp __x_copy = __x; _Tp __x_copy = __x;
#endif #endif
_GLIBCXX_MOVE_BACKWARD3(__position.base(), _GLIBCXX_MOVE_BACKWARD3(__position.base(),
this->_M_impl._M_finish - 2, this->_M_impl._M_finish - 2,
this->_M_impl._M_finish - 1); this->_M_impl._M_finish - 1);
#if __cplusplus < 201103L #if __cplusplus < 201103L
*__position = __x_copy; *__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));
#else #else
__x); *__position = std::forward<_Arg>(__arg);
#endif #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 #if __cplusplus >= 201103L
...@@ -428,44 +385,66 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -428,44 +385,66 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename... _Args> template<typename... _Args>
void void
vector<_Tp, _Alloc>:: vector<_Tp, _Alloc>::
_M_emplace_back_aux(_Args&&... __args) _M_realloc_insert(iterator __position, _Args&&... __args)
{ #else
const size_type __len = template<typename _Tp, typename _Alloc>
_M_check_len(size_type(1), "vector::_M_emplace_back_aux"); void
pointer __new_start(this->_M_allocate(__len)); vector<_Tp, _Alloc>::
pointer __new_finish(__new_start); _M_realloc_insert(iterator __position, const _Tp& __x)
__try #endif
{ {
_Alloc_traits::construct(this->_M_impl, __new_start + size(), const size_type __len =
std::forward<_Args>(__args)...); _M_check_len(size_type(1), "vector::_M_realloc_insert");
__new_finish = pointer(); 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 __new_finish
= std::__uninitialized_move_if_noexcept_a = std::__uninitialized_move_if_noexcept_a
(this->_M_impl._M_start, this->_M_impl._M_finish, (this->_M_impl._M_start, __position.base(),
__new_start, _M_get_Tp_allocator()); __new_start, _M_get_Tp_allocator());
++__new_finish; ++__new_finish;
}
__catch(...) __new_finish
{ = std::__uninitialized_move_if_noexcept_a
if (!__new_finish) (__position.base(), this->_M_impl._M_finish,
_Alloc_traits::destroy(this->_M_impl, __new_start + size()); __new_finish, _M_get_Tp_allocator());
else }
std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); __catch(...)
_M_deallocate(__new_start, __len); {
__throw_exception_again; if (!__new_finish)
} _Alloc_traits::destroy(this->_M_impl,
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, __new_start + __elems_before);
_M_get_Tp_allocator()); else
_M_deallocate(this->_M_impl._M_start, std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
this->_M_impl._M_end_of_storage _M_deallocate(__new_start, __len);
- this->_M_impl._M_start); __throw_exception_again;
this->_M_impl._M_start = __new_start; }
this->_M_impl._M_finish = __new_finish; std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
this->_M_impl._M_end_of_storage = __new_start + __len; _M_get_Tp_allocator());
} _M_deallocate(this->_M_impl._M_start,
#endif 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<typename _Tp, typename _Alloc> template<typename _Tp, typename _Alloc>
void void
...@@ -520,7 +499,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -520,7 +499,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __new_finish(__new_start); pointer __new_finish(__new_start);
__try __try
{ {
// See _M_insert_aux above. // See _M_realloc_insert above.
std::__uninitialized_fill_n_a(__new_start + __elems_before, std::__uninitialized_fill_n_a(__new_start + __elems_before,
__n, __x, __n, __x,
_M_get_Tp_allocator()); _M_get_Tp_allocator());
......
...@@ -223,8 +223,7 @@ test03() ...@@ -223,8 +223,7 @@ test03()
void void
test04() test04()
{ {
const X::special expected_ins{ 0, 3, 1, 0, 3, 0 }; const X::special expected{ 0, 3, 1, 0, 3, 0 };
const X::special expected_emp{ 0, 4, 1, 0, 4, 0 };
X::special ins, emp; X::special ins, emp;
{ {
std::vector<X> v; std::vector<X> v;
...@@ -254,8 +253,8 @@ test04() ...@@ -254,8 +253,8 @@ test04()
// std::cout << "----\n"; // std::cout << "----\n";
emp = X::sp; emp = X::sp;
} }
VERIFY( ins == expected_ins ); VERIFY( ins == emp );
VERIFY( emp == expected_emp ); VERIFY( ins == expected );
} }
// insert vs emplace xvalue reallocation // insert vs emplace xvalue reallocation
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment