Add __is_nothrow_swappable and take it into use.
authorVille Voutilainen <ville.voutilainen@gmail.com>
Fri, 5 Jun 2015 14:44:26 +0000 (17:44 +0300)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 5 Jun 2015 14:44:26 +0000 (15:44 +0100)
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

14 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/algorithmfwd.h
libstdc++-v3/include/bits/move.h
libstdc++-v3/include/bits/stl_pair.h
libstdc++-v3/include/bits/stl_queue.h
libstdc++-v3/include/bits/stl_stack.h
libstdc++-v3/include/debug/array
libstdc++-v3/include/profile/array
libstdc++-v3/include/std/array
libstdc++-v3/include/std/tuple
libstdc++-v3/include/std/type_traits
libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc [new file with mode: 0644]

index 89e0fcfae7be4f40f7d36a74eb740a21af61af0f..4efd866729df5d192cdbc34553d6f38a91b7ed4a 100644 (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.
index 1dfc4ad7b158b09e24e198437452c7ea56f4fbcb..c972f33c0f357f7188245f2e5d46105d31e626fb 100644 (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 
index 1dfd667a7164e45001a32d2ec0967ac08a9e13c3..88c4f7b3e5c814d8a82f182d9b2d36c781d98d89 100644 (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)
index 3daeb60ab5c2b244cc48bb6f5a388075e9b45a31..490b00565a0560f9f15f86bb706fa8f3800ee026 100644 (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);
index 48e1ee79c6d77ee44ef88450d63a3692b3ef0cca..5f8e6fb9ab18c4e11bd9bb7e79283df65f1e1856 100644 (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);
index 3ff307ff6ad374ae877c3aaa882ce1bcd053b962..0ed212e4307e562312bffc0db6dfcf43708c0c04 100644 (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);
index 7bb74c17664160b851ca095452c402c52a7a9f45..34e6281da5a5c5a342295d125830291af8d59664 100644 (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.
index 5198bb3af9c09569441321ac54707c0235859d69..434ca968d8452a92a747d46733f5b0d687a25410 100644 (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.
index 24be44f5b134c61b22552aa89fde311484ad2d02..40fbd46c5590b91b1c49a713f130b2abdf98ebe7 100644 (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.
index ad132bd83084af838a748ab3b12f1915bafd24af..ccea02b4ffd4667b607a31785591e6c52d0a415e 100644 (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));
index b8ec61f6892a31e5d02f591b54aa9b4c04654c4d..2eae61bb8f43e41e4a78d63e9137a216c089ce43 100644 (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
 
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc
new file mode 100644 (file)
index 0000000..93fa94b
--- /dev/null
@@ -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>;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc
new file mode 100644 (file)
index 0000000..2372349
--- /dev/null
@@ -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;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc
new file mode 100644 (file)
index 0000000..bc778b5
--- /dev/null
@@ -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), "");
+}