libstdc++/68877 Reimplement std::__is_swappable
authorDaniel Kruegler <daniel.kruegler@gmail.com>
Tue, 12 Jan 2016 21:19:58 +0000 (21:19 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 12 Jan 2016 21:19:58 +0000 (21:19 +0000)
2016-01-12  Daniel Kruegler  <daniel.kruegler@gmail.com>

PR libstdc++/68877
* include/std/type_traits: Following N4511, reimplement __is_swappable
and __is_nothrow_swappable. Move __is_swappable to namespace std,
adjust callers. Use __is_nothrow_swappable in swap.
* include/bits/move.h: Use __is_nothrow_swappable in swap.
* testsuite/20_util/is_nothrow_swappable/value.cc: Extend; remove
__is_swappable related tests.
* testsuite/20_util/is_swappable/value.cc: New.
* testsuite/20_util/is_swappable/requirements/
explicit_instantiation.cc: New.
* testsuite/20_util/is_swappable/requirements/typedefs.cc: New.
* testsuite/25_algorithms/swap/68877.cc: New.

From-SVN: r232296

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/move.h
libstdc++-v3/include/std/type_traits
libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc
libstdc++-v3/testsuite/20_util/is_swappable/requirements/explicit_instantiation.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/is_swappable/requirements/typedefs.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/is_swappable/value.cc [new file with mode: 0644]
libstdc++-v3/testsuite/25_algorithms/swap/68877.cc [new file with mode: 0644]

index 6713591..95dbb43 100644 (file)
@@ -1,3 +1,18 @@
+2016-01-12  Daniel Kruegler  <daniel.kruegler@gmail.com>
+
+       PR libstdc++/68877
+       * include/std/type_traits: Following N4511, reimplement __is_swappable
+       and __is_nothrow_swappable. Move __is_swappable to namespace std,
+       adjust callers. Use __is_nothrow_swappable in swap.
+       * include/bits/move.h: Use __is_nothrow_swappable in swap.
+       * testsuite/20_util/is_nothrow_swappable/value.cc: Extend; remove
+       __is_swappable related tests.
+       * testsuite/20_util/is_swappable/value.cc: New.
+       * testsuite/20_util/is_swappable/requirements/
+       explicit_instantiation.cc: New.
+       * testsuite/20_util/is_swappable/requirements/typedefs.cc: New.
+       * testsuite/25_algorithms/swap/68877.cc: New.
+
 2016-01-12  Jonathan Wakely  <jwakely@redhat.com>
 
        * testsuite/20_util/function/68995.cc: Test reference_wrapper cases.
index a9bcdca..afcea2d 100644 (file)
@@ -198,9 +198,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, size_t _Nm>
     inline
 #if __cplusplus >= 201103L
-    typename enable_if<__is_swappable_impl::__is_swappable<_Tp>::value>::type
+    typename enable_if<__is_swappable<_Tp>::value>::type
     swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
-    noexcept(noexcept(swap(*__a, *__b)))
+    noexcept(__is_nothrow_swappable<_Tp>::value)
 #else
     void
     swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
index 37f039b..3a2b546 100644 (file)
@@ -2587,12 +2587,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : true_type                                                                \
     { };
 
+  template <typename _Tp>
+    struct __is_swappable;
 
-   namespace __is_swappable_impl {
-     template <typename _Tp, typename=void>
-     struct __is_swappable : public false_type
-     { };
-   }
+  template <typename _Tp>
+    struct __is_nothrow_swappable;
 
   template<typename _Tp>
     inline
@@ -2604,33 +2603,58 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp, size_t _Nm>
     inline
-    typename enable_if<__is_swappable_impl::__is_swappable<_Tp>::value>::type
+    typename enable_if<__is_swappable<_Tp>::value>::type
     swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
-    noexcept(noexcept(swap(*__a, *__b)));
+    noexcept(__is_nothrow_swappable<_Tp>::value);
 
-  namespace __is_swappable_impl {
+  namespace __swappable_details {
     using std::swap;
 
-    template <typename _Tp>
-    struct __is_swappable<_Tp, __void_t<decltype(swap(declval<_Tp&>(),
-                                                      declval<_Tp&>()))>>
-    : public true_type
-    { };
+    struct __do_is_swappable_impl
+    {
+      template<typename _Tp, typename
+               = decltype(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))>
+        static true_type __test(int);
+
+      template<typename>
+        static false_type __test(...);
+    };
+
+    struct __do_is_nothrow_swappable_impl
+    {
+      template<typename _Tp>
+        static __bool_constant<
+          noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))
+        > __test(int);
+
+      template<typename>
+        static false_type __test(...);
+    };
+
   }
 
-  template <bool, typename _Tp>
+  template<typename _Tp>
+    struct __is_swappable_impl
+    : public __swappable_details::__do_is_swappable_impl
+    {
+      typedef decltype(__test<_Tp>(0)) type;
+    };
+
+  template<typename _Tp>
     struct __is_nothrow_swappable_impl
-    : public __bool_constant<noexcept(swap(declval<_Tp&>(), declval<_Tp&>()))>
-    { };
+    : public __swappable_details::__do_is_nothrow_swappable_impl
+    {
+      typedef decltype(__test<_Tp>(0)) type;
+    };
 
-  template <typename _Tp>
-    struct __is_nothrow_swappable_impl<false, _Tp> : public false_type
+  template<typename _Tp>
+    struct __is_swappable
+    : public __is_swappable_impl<_Tp>::type
     { };
 
-  template <typename _Tp>
+  template<typename _Tp>
     struct __is_nothrow_swappable
-    : public __is_nothrow_swappable_impl<
-               __is_swappable_impl::__is_swappable<_Tp>::value, _Tp>
+    : public __is_nothrow_swappable_impl<_Tp>::type
     { };
 
 _GLIBCXX_END_NAMESPACE_VERSION
index eccc0be..5f93891 100644 (file)
 namespace funny {
   struct F {};
   void swap(F&, F&) = delete;
+  void swap(F(&)[5], F(&)[5]) noexcept;
+  void swap(F(&)[6], F(&)[6]);
+  struct A {};
+  void swap(A&, A&) noexcept(false);
+}
+namespace std {
+  template<>
+  void swap<funny::A>(funny::A&, funny::A&) noexcept
+  {
+  }
+
+  template<>
+  void swap<funny::A>(funny::A(&)[3], funny::A(&)[3]) noexcept(false)
+  {
+  }
+}
+namespace ns1 {
+  struct SwapThrow {};
+  void swap(SwapThrow&, SwapThrow&);
+  void swap(SwapThrow(&)[3], SwapThrow(&)[3]) noexcept;
+}
+
+namespace ns2 {
+  struct SwapThrow {
+    SwapThrow() noexcept = default;
+    SwapThrow(const SwapThrow&) noexcept(false);
+    SwapThrow& operator=(const SwapThrow&) noexcept(false);
+  };
+}
+
+namespace ns3 {
+  struct SwapNoThrow {
+    SwapNoThrow() noexcept = default;
+    SwapNoThrow(const SwapNoThrow&) noexcept(false);
+    SwapNoThrow& operator =(const SwapNoThrow&) noexcept(false);
+  };
+  void swap(SwapNoThrow&, SwapNoThrow&) noexcept;
+}
+
+namespace ns4 {
+  struct SwapNoThrow {};
+}
+
+namespace ns5 {
+  struct SwapThrow {
+    SwapThrow() noexcept = default;
+    SwapThrow(SwapThrow&&) noexcept;
+    SwapThrow& operator=(const SwapThrow&) noexcept(false);
+  };
 }
 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, bool>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    decltype(nullptr)>(true), "");
+  static_assert(test_property<__is_nothrow_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, int[1][2]>(true), "");
+  static_assert(test_property<__is_nothrow_swappable, int[1][2][3]>(true), "");
+  static_assert(test_property<__is_nothrow_swappable, funny::F[5]>(true), "");
+  static_assert(test_property<__is_nothrow_swappable, EnumType>(true), "");
+  static_assert(test_property<__is_nothrow_swappable, PODType>(true), "");
+  static_assert(test_property<__is_nothrow_swappable, UnionType>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    construct::SE>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    construct::Empty>(true), "");
+  static_assert(test_property<__is_nothrow_swappable, void*>(true), "");
+  static_assert(test_property<__is_nothrow_swappable, void(*)()>(true), "");
+  static_assert(test_property<__is_nothrow_swappable, int const*>(true), "");
+  static_assert(test_property<__is_nothrow_swappable, ClassType*>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    int ClassType::*>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    void (ClassType::*)()>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    int (ClassType::*)() const volatile>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns1::SwapThrow[3]>(true), "");
+  static_assert(!noexcept(std::swap(std::declval<ns1::SwapThrow(&)[3]>(),
+                                    std::declval<ns1::SwapThrow(&)[3]>())),
+                                    "");
+  static_assert(test_property<__is_nothrow_swappable,
+        ns3::SwapNoThrow>(true), "");
+  static_assert(!noexcept(std::swap(std::declval<ns3::SwapNoThrow&>(),
+                                    std::declval<ns3::SwapNoThrow&>())), "");
+  static_assert(test_property<__is_nothrow_swappable,
+        ns3::SwapNoThrow[1]>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+        ns3::SwapNoThrow[3]>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+        ns3::SwapNoThrow[2][3][4]>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+        ns4::SwapNoThrow>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+        ns4::SwapNoThrow[1]>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+        ns4::SwapNoThrow[3]>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+        ns4::SwapNoThrow[2][3][4]>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+        std::pair<int, int>>(true), "");
   static_assert(test_property<__is_nothrow_swappable,
-               std::pair<int, int>>(true), "");
+        std::pair<int, int>[1]>(true), "");
   static_assert(test_property<__is_nothrow_swappable,
-               std::tuple<int>>(true), "");
+        std::pair<int, int>[1][2]>(true), "");
   static_assert(test_property<__is_nothrow_swappable,
-               std::array<int, 1>>(true), "");
+        std::tuple<int>>(true), "");
   static_assert(test_property<__is_nothrow_swappable,
-               std::queue<int>>(true), "");
+        std::tuple<int>[1]>(true), "");
   static_assert(test_property<__is_nothrow_swappable,
-               std::priority_queue<int>>(true), "");
+        std::tuple<int>[1][2]>(true), "");
   static_assert(test_property<__is_nothrow_swappable,
-               std::stack<int>>(true), "");
+        std::tuple<>>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+        std::tuple<>[1]>(true), "");
+  static_assert(test_property<__is_nothrow_swappable,
+        std::tuple<>[1][2]>(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, void>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, const void>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, void()>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    void() const>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    void() volatile>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    void() const volatile>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, const int>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, const bool>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    const int[1]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    const int[1][2]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    const int[1][2][3]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, int[]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, const int[]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, int[][1]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    const funny::F[5]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    construct::Abstract>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    construct::DelCopy>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, funny::F>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, funny::F[1]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    funny::F[1][2]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    funny::F[1][2][3]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, funny::F[6]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable, funny::A>(false), "");
+  static_assert(noexcept(std::swap(std::declval<funny::A&>(),
+                                   std::declval<funny::A&>())), "");
+  static_assert(test_property<__is_nothrow_swappable, funny::A[3]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns1::SwapThrow>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns1::SwapThrow[1]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns1::SwapThrow[3][2]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns1::SwapThrow[2][3][4]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns2::SwapThrow>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns2::SwapThrow[1]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns2::SwapThrow[2][3][4]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns5::SwapThrow>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns5::SwapThrow[1]>(false), "");
+  static_assert(test_property<__is_nothrow_swappable,
+    ns5::SwapThrow[2][3][4]>(false), "");
   static_assert(test_property<__is_nothrow_swappable,
                ThrowCopyConsClass>(false), "");
   static_assert(test_property<__is_nothrow_swappable,
diff --git a/libstdc++-v3/testsuite/20_util/is_swappable/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/is_swappable/requirements/explicit_instantiation.cc
new file mode 100644 (file)
index 0000000..c3f9343
--- /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_swappable<test_type>;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_swappable/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/is_swappable/requirements/typedefs.cc
new file mode 100644 (file)
index 0000000..a1e289b
--- /dev/null
@@ -0,0 +1,31 @@
+// { 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_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_swappable/value.cc b/libstdc++-v3/testsuite/20_util/is_swappable/value.cc
new file mode 100644 (file)
index 0000000..d594cf6
--- /dev/null
@@ -0,0 +1,185 @@
+// { 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 swap(F(&)[5], F(&)[5]);
+
+  struct F2
+  {
+    friend void swap(F2&, F2&) = delete;
+  };
+
+  struct F3
+  {
+    friend void swap(F3&, F3) {}
+  };
+}
+void test01()
+{
+  using std::__is_swappable;
+  using namespace __gnu_test;
+  // Positive tests.
+  static_assert(test_property<__is_swappable, int>(true), "");
+  static_assert(test_property<__is_swappable, bool>(true), "");
+  static_assert(test_property<__is_swappable, decltype(nullptr)>(true), "");
+  static_assert(test_property<__is_swappable, int&>(true), "");
+  static_assert(test_property<__is_swappable, int&&>(true), "");
+  static_assert(test_property<__is_swappable, int[1]>(true), "");
+  static_assert(test_property<__is_swappable, int[1][2]>(true), "");
+  static_assert(test_property<__is_swappable, int[1][2][3]>(true), "");
+  static_assert(test_property<__is_swappable, int(&)[1]>(true), "");
+  static_assert(test_property<__is_swappable, funny::F[5]>(true), "");
+  static_assert(test_property<__is_swappable, funny::F3>(true), "");
+  static_assert(test_property<__is_swappable, funny::F3[1]>(true), "");
+  static_assert(test_property<__is_swappable, funny::F3[1][2]>(true), "");
+  static_assert(test_property<__is_swappable, funny::F3[1][2][3]>(true), "");
+  static_assert(test_property<__is_swappable,
+    ThrowCopyConsClass>(true), "");
+  static_assert(test_property<__is_swappable, EnumType>(true), "");
+  static_assert(test_property<__is_swappable, PODType>(true), "");
+  static_assert(test_property<__is_swappable, UnionType>(true), "");
+  static_assert(test_property<__is_swappable, construct::SE>(true), "");
+  static_assert(test_property<__is_swappable, construct::Empty>(true), "");
+  static_assert(test_property<__is_swappable, void*>(true), "");
+  static_assert(test_property<__is_swappable, int const*>(true), "");
+  static_assert(test_property<__is_swappable, ClassType*>(true), "");
+  static_assert(test_property<__is_swappable, int ClassType::*>(true), "");
+  static_assert(test_property<__is_swappable,
+    void (ClassType::*)()>(true), "");
+  static_assert(test_property<__is_swappable,
+    construct::Nontrivial>(true), "");
+  static_assert(test_property<__is_swappable, construct::Any>(true), "");
+  static_assert(test_property<__is_swappable, construct::nAny>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::pair<int, int>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::pair<int, int>[1]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::pair<int, int>[1][2]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::pair<int, int>[1][2][3]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::pair<construct::Nontrivial, construct::Nontrivial>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::tuple<int>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::tuple<int>[1]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::tuple<int>[1][2]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::tuple<int>[1][2][3]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::tuple<>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::tuple<>[1]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::tuple<>[1][2]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::tuple<>[1][2][3]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::tuple<construct::Nontrivial>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::array<int, 1>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::array<int, 1>[1]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::array<int, 1>[1][2]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::array<int, 1>[1][2][3]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::array<construct::Nontrivial, 1>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::queue<int>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::queue<int>[1]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::queue<int>[1][2]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::queue<int>[1][2][3]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::queue<construct::Nontrivial>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::priority_queue<int>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::priority_queue<int>[1]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::priority_queue<int>[1][2]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::priority_queue<int>[1][2][3]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::priority_queue<construct::Nontrivial>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::stack<int>>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::stack<int>[1]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::stack<int>[1][2]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::stack<int>[1][2][3]>(true), "");
+  static_assert(test_property<__is_swappable,
+               std::stack<construct::Nontrivial>>(true), "");
+  // Negative tests.
+  static_assert(test_property<__is_swappable, void>(false), "");
+  static_assert(test_property<__is_swappable, const void>(false), "");
+  static_assert(test_property<__is_swappable, void()>(false), "");
+  static_assert(test_property<__is_swappable, void() const>(false), "");
+  static_assert(test_property<__is_swappable, void() volatile>(false), "");
+  static_assert(test_property<__is_swappable,
+    void() const volatile>(false), "");
+  static_assert(test_property<__is_swappable, const int>(false), "");
+  static_assert(test_property<__is_swappable, const bool>(false), "");
+  static_assert(test_property<__is_swappable, int[]>(false), "");
+  static_assert(test_property<__is_swappable, const int[]>(false), "");
+  static_assert(test_property<__is_swappable, int[][1]>(false), "");
+  static_assert(test_property<__is_swappable, const int[1]>(false), "");
+  static_assert(test_property<__is_swappable, const int[1][2]>(false), "");
+  static_assert(test_property<__is_swappable, const int[1][2][3]>(false), "");
+  static_assert(test_property<__is_swappable, construct::DelCopy>(false), "");
+  static_assert(test_property<__is_swappable,
+    construct::Abstract>(false), "");
+  static_assert(test_property<__is_swappable,
+    construct::NontrivialUnion>(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_swappable, funny::F[1][2]>(false), "");
+  static_assert(test_property<__is_swappable, funny::F[1][2][3]>(false), "");
+  static_assert(test_property<__is_swappable, funny::F[4]>(false), "");
+  static_assert(test_property<__is_swappable, construct::DelCopy>(false), "");
+  static_assert(test_property<__is_swappable,
+     DeletedCopyAssignClass>(false), "");
+  static_assert(test_property<__is_swappable,
+     DeletedMoveAssignClass>(false), "");
+  static_assert(test_property<__is_swappable, funny::F2>(false), "");
+  static_assert(test_property<__is_swappable, funny::F2[1]>(false), "");
+  static_assert(test_property<__is_swappable, funny::F2[1][2]>(false), "");
+  static_assert(test_property<__is_swappable, funny::F2[1][2][3]>(false), "");
+  static_assert(test_property<__is_swappable, funny::F2[4]>(false), "");
+  static_assert(test_property<__is_swappable, funny::F2[5]>(false), "");
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/swap/68877.cc b/libstdc++-v3/testsuite/25_algorithms/swap/68877.cc
new file mode 100644 (file)
index 0000000..dd5aa8c
--- /dev/null
@@ -0,0 +1,33 @@
+// { 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 <utility>
+
+// libstdc++/68877
+void test01()
+{
+  int x[2][3];
+  int y[2][3];
+
+  std::swap(x, y);
+
+  using std::swap;
+  swap(x, y);
+}