+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.
_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
* @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
// 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)
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);
#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);
#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);
#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);
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.
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.
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.
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));
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));
: 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
--- /dev/null
+// { 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>;
+}
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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), "");
+}