Add __is_nothrow_swappable and take it into use.

2015-06-04  Ville Voutilainen  <ville.voutilainen@gmail.com>

	Add __is_nothrow_swappable and take it into use.
	* include/bits/algorithmfwd.h (swap): Only declare for C++98 mode.
	* include/bits/move.h (swap): Add constraints in C++11 and later.
	* include/bits/stl_pair.h (swap): Use __is_nothrow_swappable
	for the free swap function for pair.
	* include/bits/stl_queue.h (swap): Use __is_nothrow_swappable
	for the free swap functions for queue and priority_queue.
	* include/bits/stl_stack.h (swap): Use __is_nothrow_swappable
	for the free swap function for stack.
	* include/debug/array (swap): Use __is_nothrow_swappable
	for the free swap function for array.
	* include/profile/array (swap): Likewise.
	* include/std/array (swap): Likewise.
	* include/std/tuple (_Tuple_impl::_M_swap): Use __is_nothrow_swappable.
	* include/std/type_traits (__is_swappable_impl::__is_swappable,
	__is_nothrow_swappable_impl, __is_nothrow_swappable): New.
	* testsuite/20_util/is_nothrow_swappable/requirements/
	explicit_instantiation.cc: New.
	* testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc:
	New.
	* testsuite/20_util/is_nothrow_swappable/value.cc: New.

From-SVN: r224153
This commit is contained in:
Ville Voutilainen 2015-06-05 17:44:26 +03:00 committed by Jonathan Wakely
parent ac59f9beec
commit ddb63209a8
14 changed files with 234 additions and 29 deletions

View File

@ -1,3 +1,27 @@
2015-06-04 Ville Voutilainen <ville.voutilainen@gmail.com>
Add __is_nothrow_swappable and take it into use.
* include/bits/algorithmfwd.h (swap): Only declare for C++98 mode.
* include/bits/move.h (swap): Add constraints in C++11 and later.
* include/bits/stl_pair.h (swap): Use __is_nothrow_swappable
for the free swap function for pair.
* include/bits/stl_queue.h (swap): Use __is_nothrow_swappable
for the free swap functions for queue and priority_queue.
* include/bits/stl_stack.h (swap): Use __is_nothrow_swappable
for the free swap function for stack.
* include/debug/array (swap): Use __is_nothrow_swappable
for the free swap function for array.
* include/profile/array (swap): Likewise.
* include/std/array (swap): Likewise.
* include/std/tuple (_Tuple_impl::_M_swap): Use __is_nothrow_swappable.
* include/std/type_traits (__is_swappable_impl::__is_swappable,
__is_nothrow_swappable_impl, __is_nothrow_swappable): New.
* testsuite/20_util/is_nothrow_swappable/requirements/
explicit_instantiation.cc: New.
* testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc:
New.
* testsuite/20_util/is_nothrow_swappable/value.cc: New.
2015-06-03 François Dumont fdumont@gcc.gnu.org>
* testsuite/23_containers/list/61347.cc: Add dg-require-normal-mode.

View File

@ -566,22 +566,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_BIter
stable_partition(_BIter, _BIter, _Predicate);
template<typename _Tp>
void
swap(_Tp&, _Tp&)
#if __cplusplus >= 201103L
noexcept(__and_<is_nothrow_move_constructible<_Tp>,
is_nothrow_move_assignable<_Tp>>::value)
#endif
;
#if __cplusplus < 201103L
// For C++11 swap() is declared in <type_traits>.
template<typename _Tp, size_t _Nm>
void
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
#if __cplusplus >= 201103L
noexcept(noexcept(swap(*__a, *__b)))
inline void
swap(_Tp& __a, _Tp& __b);
template<typename _Tp, size_t _Nm>
inline void
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]);
#endif
;
template<typename _FIter1, typename _FIter2>
_FIter2

View File

@ -172,11 +172,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @return Nothing.
*/
template<typename _Tp>
inline void
swap(_Tp& __a, _Tp& __b)
inline
#if __cplusplus >= 201103L
typename enable_if<__and_<is_move_constructible<_Tp>,
is_move_assignable<_Tp>>::value>::type
swap(_Tp& __a, _Tp& __b)
noexcept(__and_<is_nothrow_move_constructible<_Tp>,
is_nothrow_move_assignable<_Tp>>::value)
#else
void
swap(_Tp& __a, _Tp& __b)
#endif
{
// concept requirements
@ -191,10 +196,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// DR 809. std::swap should be overloaded for array types.
/// Swap the contents of two arrays.
template<typename _Tp, size_t _Nm>
inline void
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
inline
#if __cplusplus >= 201103L
typename enable_if<__is_swappable_impl::__is_swappable<_Tp>::value>::type
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
noexcept(noexcept(swap(*__a, *__b)))
#else
void
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
#endif
{
for (size_t __n = 0; __n < _Nm; ++__n)

View File

@ -192,8 +192,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
swap(pair& __p)
noexcept(noexcept(swap(first, __p.first))
&& noexcept(swap(second, __p.second)))
noexcept(__is_nothrow_swappable<_T1>::value
&& __is_nothrow_swappable<_T2>::value)
{
using std::swap;
swap(first, __p.first);

View File

@ -247,7 +247,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
void
swap(queue& __q)
noexcept(noexcept(swap(c, __q.c)))
noexcept(__is_nothrow_swappable<_Tp>::value)
{
using std::swap;
swap(c, __q.c);
@ -541,7 +541,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
void
swap(priority_queue& __pq)
noexcept(noexcept(swap(c, __pq.c)) && noexcept(swap(comp, __pq.comp)))
noexcept(__is_nothrow_swappable<_Tp>::value
&& __is_nothrow_swappable<_Compare>::value)
{
using std::swap;
swap(c, __pq.c);

View File

@ -221,7 +221,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
void
swap(stack& __s)
noexcept(noexcept(swap(c, __s.c)))
noexcept(__is_nothrow_swappable<_Tp>::value)
{
using std::swap;
swap(c, __s.c);

View File

@ -84,7 +84,7 @@ namespace __debug
void
swap(array& __other)
noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
noexcept(__is_nothrow_swappable<_Tp>::value)
{ std::swap_ranges(begin(), end(), __other.begin()); }
// Iterators.

View File

@ -63,7 +63,7 @@ namespace __profile
void
swap(array& __other)
noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
noexcept(__is_nothrow_swappable<_Tp>::value)
{ std::swap_ranges(begin(), end(), __other.begin()); }
// Iterators.

View File

@ -113,7 +113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void
swap(array& __other)
noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
noexcept(__is_nothrow_swappable<_Tp>::value)
{ std::swap_ranges(begin(), end(), __other.begin()); }
// Iterators.

View File

@ -324,9 +324,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
protected:
void
_M_swap(_Tuple_impl& __in)
noexcept(noexcept(swap(std::declval<_Head&>(),
std::declval<_Head&>()))
&& noexcept(_M_tail(__in)._M_swap(_M_tail(__in))))
noexcept(__is_nothrow_swappable<_Head>::value
&& noexcept(_M_tail(__in)._M_swap(_M_tail(__in))))
{
using std::swap;
swap(_M_head(*this), _M_head(__in));
@ -451,7 +450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
protected:
void
_M_swap(_Tuple_impl& __in)
noexcept(noexcept(swap(std::declval<_Head&>(), std::declval<_Head&>())))
noexcept(__is_nothrow_swappable<_Head>::value)
{
using std::swap;
swap(_M_head(*this), _M_head(__in));

View File

@ -2427,6 +2427,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: true_type \
{ };
namespace __is_swappable_impl {
template <typename _Tp, typename=void>
struct __is_swappable : public false_type
{ };
}
template<typename _Tp>
inline
typename enable_if<__and_<is_move_constructible<_Tp>,
is_move_assignable<_Tp>>::value>::type
swap(_Tp&, _Tp&)
noexcept(__and_<is_nothrow_move_constructible<_Tp>,
is_nothrow_move_assignable<_Tp>>::value);
template<typename _Tp, size_t _Nm>
inline
typename enable_if<__is_swappable_impl::__is_swappable<_Tp>::value>::type
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
noexcept(noexcept(swap(*__a, *__b)));
namespace __is_swappable_impl {
using std::swap;
template <typename _Tp>
struct __is_swappable<_Tp, __void_t<decltype(swap(declval<_Tp&>(),
declval<_Tp&>()))>>
: public true_type
{ };
}
template <bool, typename _Tp>
struct __is_nothrow_swappable_impl
: public __bool_constant<noexcept(swap(declval<_Tp&>(), declval<_Tp&>()))>
{ };
template <typename _Tp>
struct __is_nothrow_swappable_impl<false, _Tp> : public false_type
{ };
template <typename _Tp>
struct __is_nothrow_swappable
: public __is_nothrow_swappable_impl<
__is_swappable_impl::__is_swappable<_Tp>::value, _Tp>
{ };
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std

View File

@ -0,0 +1,27 @@
// { dg-options "-std=gnu++11" }
// { dg-do compile }
// Copyright (C) 2015 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 <type_traits>
namespace std
{
typedef short test_type;
template struct std::__is_nothrow_swappable<test_type>;
}

View File

@ -0,0 +1,32 @@
// { dg-options "-std=gnu++11" }
// { dg-do compile }
// Copyright (C) 2015 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 <type_traits>
void test01()
{
// Check for required typedefs
typedef std::__is_nothrow_swappable<int> test_type;
typedef test_type::value_type value_type;
typedef test_type::type type;
typedef test_type::type::value_type type_value_type;
typedef test_type::type::type type_type;
}

View File

@ -0,0 +1,72 @@
// { dg-options "-std=gnu++11" }
// { dg-do compile }
// Copyright (C) 2015 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 <type_traits>
#include <testsuite_tr1.h>
#include <utility>
#include <array>
#include <tuple>
#include <queue>
#include <stack>
namespace funny {
struct F {};
void swap(F&, F&) = delete;
}
void test01()
{
using std::__is_nothrow_swappable;
using std::__is_swappable_impl::__is_swappable;
using namespace __gnu_test;
// Positive tests.
static_assert(test_property<__is_swappable, int>(true), "");
static_assert(test_property<__is_nothrow_swappable, int>(true), "");
static_assert(test_property<__is_nothrow_swappable, int[1]>(true), "");
static_assert(test_property<__is_nothrow_swappable,
std::pair<int, int>>(true), "");
static_assert(test_property<__is_nothrow_swappable,
std::tuple<int>>(true), "");
static_assert(test_property<__is_nothrow_swappable,
std::array<int, 1>>(true), "");
static_assert(test_property<__is_nothrow_swappable,
std::queue<int>>(true), "");
static_assert(test_property<__is_nothrow_swappable,
std::priority_queue<int>>(true), "");
static_assert(test_property<__is_nothrow_swappable,
std::stack<int>>(true), "");
// Negative tests.
static_assert(test_property<__is_swappable, construct::DelCopy>(false), "");
static_assert(test_property<__is_swappable, funny::F>(false), "");
static_assert(test_property<__is_swappable, funny::F[1]>(false), "");
static_assert(test_property<__is_nothrow_swappable,
ThrowCopyConsClass>(false), "");
static_assert(test_property<__is_nothrow_swappable,
std::pair<ThrowCopyConsClass, ThrowCopyConsClass>>(false), "");
static_assert(test_property<__is_nothrow_swappable,
std::tuple<ThrowCopyConsClass>>(false), "");
static_assert(test_property<__is_nothrow_swappable,
std::array<ThrowCopyConsClass, 1>>(false), "");
static_assert(test_property<__is_nothrow_swappable,
std::queue<ThrowCopyConsClass>>(false), "");
static_assert(test_property<__is_nothrow_swappable,
std::priority_queue<ThrowCopyConsClass>>(false), "");
static_assert(test_property<__is_nothrow_swappable,
std::stack<ThrowCopyConsClass>>(false), "");
}