move.h (struct __move_if_noexcept_cond): Add.

2011-06-07  Paolo Carlini  <paolo.carlini@oracle.com>

	* include/bits/move.h (struct __move_if_noexcept_cond): Add.
	(move_if_noexcept): Use the latter.
	* include/bits/stl_iterator.h (__make_move_if_noexcept_iterator,
	_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR): Add.
	* include/bits/stl_uninitialized.h
	(__uninitialized_move_if_noexcept_a): Add.
	* include/bits/vector.tcc (vector<>::reserve): Use
	_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR.
	(vector<>::_M_insert_aux, _M_fill_insert, _M_default_append,
	_M_range_insert): Use __uninitialized_move_if_noexcept_a.
	* testsuite/23_containers/vector/modifiers/moveable2.cc: New.
	* testsuite/23_containers/vector/capacity/resize/moveable2.cc:
	Likewise.
	* testsuite/23_containers/vector/capacity/reserve/moveable2.cc:
	Likewise.

From-SVN: r174756
This commit is contained in:
Paolo Carlini 2011-06-07 16:11:36 +00:00 committed by Paolo Carlini
parent 06bc3ec790
commit 74a2a1b4f6
9 changed files with 276 additions and 45 deletions

View File

@ -1,3 +1,21 @@
2011-06-07 Paolo Carlini <paolo.carlini@oracle.com>
* include/bits/move.h (struct __move_if_noexcept_cond): Add.
(move_if_noexcept): Use the latter.
* include/bits/stl_iterator.h (__make_move_if_noexcept_iterator,
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR): Add.
* include/bits/stl_uninitialized.h
(__uninitialized_move_if_noexcept_a): Add.
* include/bits/vector.tcc (vector<>::reserve): Use
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR.
(vector<>::_M_insert_aux, _M_fill_insert, _M_default_append,
_M_range_insert): Use __uninitialized_move_if_noexcept_a.
* testsuite/23_containers/vector/modifiers/moveable2.cc: New.
* testsuite/23_containers/vector/capacity/resize/moveable2.cc:
Likewise.
* testsuite/23_containers/vector/capacity/reserve/moveable2.cc:
Likewise.
2011-06-07 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/49293

View File

@ -82,6 +82,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
template<typename _Tp>
struct __move_if_noexcept_cond
: public __and_<__not_<is_nothrow_move_constructible<_Tp>>,
is_copy_constructible<_Tp>>::type { };
/**
* @brief Move unless it could throw and the type is copyable.
* @ingroup utilities
@ -90,9 +96,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _Tp>
inline typename
conditional<__and_<__not_<is_nothrow_move_constructible<_Tp>>,
is_copy_constructible<_Tp>>::value,
const _Tp&, _Tp&&>::type
conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type
move_if_noexcept(_Tp& __x) noexcept
{ return std::move(__x); }

View File

@ -1118,14 +1118,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
make_move_iterator(const _Iterator& __i)
{ return move_iterator<_Iterator>(__i); }
template<typename _Iterator, typename _ReturnType
= typename conditional<__move_if_noexcept_cond
<typename iterator_traits<_Iterator>::value_type>::value,
_Iterator, move_iterator<_Iterator>>::type>
inline _ReturnType
__make_move_if_noexcept_iterator(_Iterator __i)
{ return _ReturnType(__i); }
// @} group iterators
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) std::make_move_iterator(_Iter)
#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) \
std::__make_move_if_noexcept_iterator(_Iter)
#else
#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) (_Iter)
#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter)
#endif // __GXX_EXPERIMENTAL_CXX0X__
#endif

View File

@ -269,6 +269,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__result, __alloc);
}
template<typename _InputIterator, typename _ForwardIterator,
typename _Allocator>
inline _ForwardIterator
__uninitialized_move_if_noexcept_a(_InputIterator __first,
_InputIterator __last,
_ForwardIterator __result,
_Allocator& __alloc)
{
return std::__uninitialized_copy_a
(_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first),
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc);
}
template<typename _ForwardIterator, typename _Tp, typename _Allocator>
void
__uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,

View File

@ -72,8 +72,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
const size_type __old_size = size();
pointer __tmp = _M_allocate_and_copy(__n,
_GLIBCXX_MAKE_MOVE_ITERATOR(this->_M_impl._M_start),
_GLIBCXX_MAKE_MOVE_ITERATOR(this->_M_impl._M_finish));
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start),
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish));
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@ -337,17 +337,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
__new_finish = 0;
__new_finish =
std::__uninitialized_move_a(this->_M_impl._M_start,
__position.base(), __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;
__new_finish =
std::__uninitialized_move_a(__position.base(),
this->_M_impl._M_finish,
__new_finish,
_M_get_Tp_allocator());
__new_finish
= std::__uninitialized_move_if_noexcept_a
(__position.base(), this->_M_impl._M_finish,
__new_finish, _M_get_Tp_allocator());
}
__catch(...)
{
@ -423,18 +423,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_get_Tp_allocator());
__new_finish = 0;
__new_finish =
std::__uninitialized_move_a(this->_M_impl._M_start,
__position.base(),
__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 += __n;
__new_finish =
std::__uninitialized_move_a(__position.base(),
this->_M_impl._M_finish,
__new_finish,
_M_get_Tp_allocator());
__new_finish
= std::__uninitialized_move_if_noexcept_a
(__position.base(), this->_M_impl._M_finish,
__new_finish, _M_get_Tp_allocator());
}
__catch(...)
{
@ -484,11 +483,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __new_finish(__new_start);
__try
{
__new_finish =
std::__uninitialized_move_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, this->_M_impl._M_finish,
__new_start, _M_get_Tp_allocator());
std::__uninitialized_default_n_a(__new_finish, __n,
_M_get_Tp_allocator());
__new_finish += __n;
@ -577,20 +575,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __new_finish(__new_start);
__try
{
__new_finish =
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,
_M_get_Tp_allocator());
__new_finish =
std::__uninitialized_move_a(__position.base(),
this->_M_impl._M_finish,
__new_finish,
_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
= std::__uninitialized_copy_a(__first, __last,
__new_finish,
_M_get_Tp_allocator());
__new_finish
= std::__uninitialized_move_if_noexcept_a
(__position.base(), this->_M_impl._M_finish,
__new_finish, _M_get_Tp_allocator());
}
__catch(...)
{

View File

@ -0,0 +1,45 @@
// { dg-options "-std=gnu++0x" }
// 2011-06-07 Paolo Carlini <paolo.carlini@oracle.com>
// Copyright (C) 2011 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 3, 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 COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_rvalref.h>
void
test01()
{
bool test __attribute__((unused)) = true;
using namespace __gnu_test;
std::vector<throwing_move_constructor> v(5);
v.reserve(50);
VERIFY( v.capacity() >= 50 );
v.reserve(500);
VERIFY( v.capacity() >= 500 );
}
int main()
{
test01();
return 0;
}

View File

@ -0,0 +1,57 @@
// { dg-options "-std=gnu++0x" }
// 2011-06-07 Paolo Carlini <paolo.carlini@oracle.com>
// Copyright (C) 2011 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 3, 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 COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_rvalref.h>
void
test01()
{
bool test __attribute__((unused)) = true;
using namespace __gnu_test;
std::vector<throwing_move_constructor> v(5);
v.resize(50);
VERIFY( v.size() == 50 );
v.reserve(200);
VERIFY( v.capacity() >= 200 );
v.resize(100);
VERIFY( v.size() == 100 );
v.resize(500, throwing_move_constructor());
VERIFY( v.size() == 500 );
v.reserve(2000);
VERIFY( v.capacity() >= 2000 );
v.resize(1000, throwing_move_constructor());
VERIFY( v.size() == 1000 );
}
int main()
{
test01();
return 0;
}

View File

@ -0,0 +1,77 @@
// { dg-options "-std=gnu++0x" }
// 2011-06-07 Paolo Carlini <paolo.carlini@oracle.com>
// Copyright (C) 2011 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 3, 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 COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_rvalref.h>
void
test01()
{
bool test __attribute__((unused)) = true;
using namespace __gnu_test;
std::vector<throwing_move_constructor> v1;
throwing_move_constructor tmc;
v1.push_back(tmc);
VERIFY( v1.size() == 1 );
v1.push_back(tmc);
VERIFY( v1.size() == 2 );
v1.insert(v1.end(), tmc);
VERIFY( v1.size() == 3 );
v1.insert(v1.end(), 100, tmc);
VERIFY( v1.size() == 103 );
v1.insert(v1.end(), 10, tmc);
VERIFY( v1.size() == 113 );
v1.insert(v1.end(), 1, tmc);
VERIFY( v1.size() == 114 );
std::vector<throwing_move_constructor> v2;
throwing_move_constructor tmca[]
= { throwing_move_constructor(), throwing_move_constructor(),
throwing_move_constructor(), throwing_move_constructor() };
v2.insert(v2.end(), tmca, tmca + 1);
VERIFY( v2.size() == 1 );
v2.insert(v2.end(), tmca, tmca + 4);
VERIFY( v2.size() == 5 );
v2.insert(v2.end(), tmca, tmca + 2);
VERIFY( v2.size() == 7 );
v2.insert(v2.end(), tmca, tmca + 1);
VERIFY( v2.size() == 8 );
}
int main()
{
test01();
return 0;
}

View File

@ -117,7 +117,7 @@ namespace __gnu_test
++copycount;
}
copycounter(copycounter&& in)
copycounter(copycounter&& in) noexcept
{
bool test __attribute__((unused)) = true;
VERIFY( in.valid == true );
@ -156,7 +156,7 @@ namespace __gnu_test
return *this;
}
~copycounter()
~copycounter() noexcept
{ valid = false; }
};
@ -246,6 +246,16 @@ namespace __gnu_test
return lh.val < rh.val;
}
struct throwing_move_constructor
{
throwing_move_constructor() = default;
throwing_move_constructor(throwing_move_constructor&&)
{ throw 1; }
throwing_move_constructor(const throwing_move_constructor&) = default;
};
} // namespace __gnu_test
namespace std