public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [libstdc++ PATCH] Implement __is_nothrow_swappable and use it
@ 2015-05-01  9:47 Ville Voutilainen
  2015-05-01  9:55 ` Ville Voutilainen
  2015-06-05 14:58 ` Jonathan Wakely
  0 siblings, 2 replies; 3+ messages in thread
From: Ville Voutilainen @ 2015-05-01  9:47 UTC (permalink / raw)
  To: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 2150 bytes --]

This patch partially solves the problem described in N4426, which is
basically LWG
issue 2456, which in turn is caused by CWG DR 1330. Some remarks:
- the __is_swappable and __is_nothrow_swappable are at this time not
meant to be general traits, they make the shortcut of automatically transforming
their template parameter into a reference, which the truly general trait
as described in N4426 wouldn't do.
- swap is now constrained..
- ..which means that everything from bits/move.h moves to type_traits since
swap now needs type_traits. type_traits becomes ok to include in pre-c++14
modes, but only enables the parts that work in pre-c++14 modes.
- this patch does _not_ yet implement N4426.

Tested on Linux-x64.

2015-05-01  Ville Voutilainen  <ville.voutilainen@gmail.com>
    Add __is_nothrow_swappable and take it into use.
    * libstdc++-v3/include/bits/algorithmfwd.h: Add constraints to the
    forward-declaration of swap.
    * include/bits/move.h: Move everything in it to..
    * include/type_traits: ..here.
    * include/type_traits (__swappable_impl::__swappable,
    __is_nothrow_swappable_impl, __is_nothrow_swappable): New.
    * 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 (_M_swap): Use __is_nothrow_swappable.
    * testsuite/20_util/forward/c_neg.cc: Adjust.
    * testsuite/20_util/forward/f_neg.cc: Likewise.
    * testsuite/20_util/headers/type_traits/std_c++0x_neg.cc: Remove.
    * testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc:
New.
    * testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc: Likewise.
    * testsuite/20_util/is_nothrow_swappable/value.cc: Likewise.

[-- Attachment #2: is_nothrow_swappable.diff --]
[-- Type: text/plain, Size: 25602 bytes --]

diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h
index 1dfc4ad..0e37307 100644
--- a/libstdc++-v3/include/bits/algorithmfwd.h
+++ b/libstdc++-v3/include/bits/algorithmfwd.h
@@ -567,7 +567,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     stable_partition(_BIter, _BIter, _Predicate);
 
   template<typename _Tp> 
-    void 
+#if __cplusplus >= 201103L
+    typename enable_if<__and_<is_move_constructible<_Tp>,
+	            is_move_assignable<_Tp>>::value>::type
+#else
+    void
+#endif
     swap(_Tp&, _Tp&)
 #if __cplusplus >= 201103L
     noexcept(__and_<is_nothrow_move_constructible<_Tp>,
@@ -576,7 +581,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     ;
 
   template<typename _Tp, size_t _Nm>
+#if __cplusplus >= 201103L
+    typename enable_if<__and_<is_move_constructible<_Tp>,
+	            is_move_assignable<_Tp>>::value>::type
+#else
     void
+#endif
     swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
 #if __cplusplus >= 201103L
     noexcept(noexcept(swap(*__a, *__b)))
diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h
index 1dfd667..96e2e51 100644
--- a/libstdc++-v3/include/bits/move.h
+++ b/libstdc++-v3/include/bits/move.h
@@ -30,179 +30,7 @@
 #ifndef _MOVE_H
 #define _MOVE_H 1
 
-#include <bits/c++config.h>
-#include <bits/concept_check.h>
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
-  // Used, in C++03 mode too, by allocators, etc.
-  /**
-   *  @brief Same as C++11 std::addressof
-   *  @ingroup utilities
-   */
-  template<typename _Tp>
-    inline _Tp*
-    __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
-    {
-      return reinterpret_cast<_Tp*>
-	(&const_cast<char&>(reinterpret_cast<const volatile char&>(__r)));
-    }
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-
-#if __cplusplus >= 201103L
 #include <type_traits> // Brings in std::declval too.
 
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
-  /**
-   *  @addtogroup utilities
-   *  @{
-   */
-
-  /**
-   *  @brief  Forward an lvalue.
-   *  @return The parameter cast to the specified type.
-   *
-   *  This function is used to implement "perfect forwarding".
-   */
-  template<typename _Tp>
-    constexpr _Tp&&
-    forward(typename std::remove_reference<_Tp>::type& __t) noexcept
-    { return static_cast<_Tp&&>(__t); }
-
-  /**
-   *  @brief  Forward an rvalue.
-   *  @return The parameter cast to the specified type.
-   *
-   *  This function is used to implement "perfect forwarding".
-   */
-  template<typename _Tp>
-    constexpr _Tp&&
-    forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
-    {
-      static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
-		    " substituting _Tp is an lvalue reference type");
-      return static_cast<_Tp&&>(__t);
-    }
-
-  /**
-   *  @brief  Convert a value to an rvalue.
-   *  @param  __t  A thing of arbitrary type.
-   *  @return The parameter cast to an rvalue-reference to allow moving it.
-  */
-  template<typename _Tp>
-    constexpr typename std::remove_reference<_Tp>::type&&
-    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  Conditionally convert a value to an rvalue.
-   *  @param  __x  A thing of arbitrary type.
-   *  @return The parameter, possibly cast to an rvalue-reference.
-   *
-   *  Same as std::move unless the type's move constructor could throw and the
-   *  type is copyable, in which case an lvalue-reference is returned instead.
-   */
-  template<typename _Tp>
-    constexpr typename
-    conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type
-    move_if_noexcept(_Tp& __x) noexcept
-    { return std::move(__x); }
-
-  // declval, from type_traits.
-
-  /**
-   *  @brief Returns the actual address of the object or function
-   *         referenced by r, even in the presence of an overloaded
-   *         operator&.
-   *  @param  __r  Reference to an object or function.
-   *  @return   The actual address.
-  */
-  template<typename _Tp>
-    inline _Tp*
-    addressof(_Tp& __r) noexcept
-    { return std::__addressof(__r); }
-
-  // C++11 version of std::exchange for internal use.
-  template <typename _Tp, typename _Up = _Tp>
-    inline _Tp
-    __exchange(_Tp& __obj, _Up&& __new_val)
-    {
-      _Tp __old_val = std::move(__obj);
-      __obj = std::forward<_Up>(__new_val);
-      return __old_val;
-    }
-
-  /// @} group utilities
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-
-#define _GLIBCXX_MOVE(__val) std::move(__val)
-#define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val)
-#else
-#define _GLIBCXX_MOVE(__val) (__val)
-#define _GLIBCXX_FORWARD(_Tp, __val) (__val)
-#endif
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
-  /**
-   *  @addtogroup utilities
-   *  @{
-   */
-
-  /**
-   *  @brief Swaps two values.
-   *  @param  __a  A thing of arbitrary type.
-   *  @param  __b  Another thing of arbitrary type.
-   *  @return   Nothing.
-  */
-  template<typename _Tp>
-    inline void
-    swap(_Tp& __a, _Tp& __b)
-#if __cplusplus >= 201103L
-    noexcept(__and_<is_nothrow_move_constructible<_Tp>,
-	            is_nothrow_move_assignable<_Tp>>::value)
-#endif
-    {
-      // concept requirements
-      __glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
-
-      _Tp __tmp = _GLIBCXX_MOVE(__a);
-      __a = _GLIBCXX_MOVE(__b);
-      __b = _GLIBCXX_MOVE(__tmp);
-    }
-
-  // _GLIBCXX_RESOLVE_LIB_DEFECTS
-  // 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])
-#if __cplusplus >= 201103L
-    noexcept(noexcept(swap(*__a, *__b)))
-#endif
-    {
-      for (size_t __n = 0; __n < _Nm; ++__n)
-	swap(__a[__n], __b[__n]);
-    }
-
-  /// @} group utilities
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
 
 #endif /* _MOVE_H */
diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index 3daeb60..490b005 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -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);
diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h
index 48e1ee7..5f8e6fb 100644
--- a/libstdc++-v3/include/bits/stl_queue.h
+++ b/libstdc++-v3/include/bits/stl_queue.h
@@ -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);
diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h
index 3ff307f..0ed212e 100644
--- a/libstdc++-v3/include/bits/stl_stack.h
+++ b/libstdc++-v3/include/bits/stl_stack.h
@@ -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);
diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array
index 31d146e..9bd1f3b 100644
--- a/libstdc++-v3/include/debug/array
+++ b/libstdc++-v3/include/debug/array
@@ -83,7 +83,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.
diff --git a/libstdc++-v3/include/profile/array b/libstdc++-v3/include/profile/array
index a90e396..4c406d2 100644
--- a/libstdc++-v3/include/profile/array
+++ b/libstdc++-v3/include/profile/array
@@ -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.
diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index 429506b..72d4649 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -105,7 +105,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.
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index e500a76..5cd6d03 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -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));
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 03e198a..ea35bc1 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -31,12 +31,12 @@
 
 #pragma GCC system_header
 
+#include <bits/c++config.h>
+#include <bits/concept_check.h>
+
 #if __cplusplus < 201103L
-# include <bits/c++0x_warning.h>
 #else
 
-#include <bits/c++config.h>
-
 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
 # if defined (__UINT_LEAST16_TYPE__) && defined(__UINT_LEAST32_TYPE__)
 namespace std
@@ -2427,4 +2427,221 @@ _GLIBCXX_END_NAMESPACE_VERSION
 
 #endif  // C++11
 
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  // Used, in C++03 mode too, by allocators, etc.
+  /**
+   *  @brief Same as C++11 std::addressof
+   *  @ingroup utilities
+   */
+  template<typename _Tp>
+    inline _Tp*
+    __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
+    {
+      return reinterpret_cast<_Tp*>
+	(&const_cast<char&>(reinterpret_cast<const volatile char&>(__r)));
+    }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+
+#if __cplusplus >= 201103L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   *  @addtogroup utilities
+   *  @{
+   */
+
+  /**
+   *  @brief  Forward an lvalue.
+   *  @return The parameter cast to the specified type.
+   *
+   *  This function is used to implement "perfect forwarding".
+   */
+  template<typename _Tp>
+    constexpr _Tp&&
+    forward(typename std::remove_reference<_Tp>::type& __t) noexcept
+    { return static_cast<_Tp&&>(__t); }
+
+  /**
+   *  @brief  Forward an rvalue.
+   *  @return The parameter cast to the specified type.
+   *
+   *  This function is used to implement "perfect forwarding".
+   */
+  template<typename _Tp>
+    constexpr _Tp&&
+    forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
+    {
+      static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
+		    " substituting _Tp is an lvalue reference type");
+      return static_cast<_Tp&&>(__t);
+    }
+
+  /**
+   *  @brief  Convert a value to an rvalue.
+   *  @param  __t  A thing of arbitrary type.
+   *  @return The parameter cast to an rvalue-reference to allow moving it.
+  */
+  template<typename _Tp>
+    constexpr typename std::remove_reference<_Tp>::type&&
+    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  Conditionally convert a value to an rvalue.
+   *  @param  __x  A thing of arbitrary type.
+   *  @return The parameter, possibly cast to an rvalue-reference.
+   *
+   *  Same as std::move unless the type's move constructor could throw and the
+   *  type is copyable, in which case an lvalue-reference is returned instead.
+   */
+  template<typename _Tp>
+    constexpr typename
+    conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type
+    move_if_noexcept(_Tp& __x) noexcept
+    { return std::move(__x); }
+
+  // declval, from type_traits.
+
+  /**
+   *  @brief Returns the actual address of the object or function
+   *         referenced by r, even in the presence of an overloaded
+   *         operator&.
+   *  @param  __r  Reference to an object or function.
+   *  @return   The actual address.
+  */
+  template<typename _Tp>
+    inline _Tp*
+    addressof(_Tp& __r) noexcept
+    { return std::__addressof(__r); }
+
+  // C++11 version of std::exchange for internal use.
+  template <typename _Tp, typename _Up = _Tp>
+    inline _Tp
+    __exchange(_Tp& __obj, _Up&& __new_val)
+    {
+      _Tp __old_val = std::move(__obj);
+      __obj = std::forward<_Up>(__new_val);
+      return __old_val;
+    }
+
+  /// @} group utilities
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#define _GLIBCXX_MOVE(__val) std::move(__val)
+#define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val)
+#else
+#define _GLIBCXX_MOVE(__val) (__val)
+#define _GLIBCXX_FORWARD(_Tp, __val) (__val)
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   *  @addtogroup utilities
+   *  @{
+   */
+
+  /**
+   *  @brief Swaps two values.
+   *  @param  __a  A thing of arbitrary type.
+   *  @param  __b  Another thing of arbitrary type.
+   *  @return   Nothing.
+  */
+  template<typename _Tp>
+    inline
+#if __cplusplus >= 201103L
+    typename enable_if<__and_<is_move_constructible<_Tp>,
+	            is_move_assignable<_Tp>>::value>::type
+#else
+    void
+#endif
+    swap(_Tp& __a, _Tp& __b)
+#if __cplusplus >= 201103L
+    noexcept(__and_<is_nothrow_move_constructible<_Tp>,
+	            is_nothrow_move_assignable<_Tp>>::value)
+#endif
+    {
+      // concept requirements
+      __glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
+
+      _Tp __tmp = _GLIBCXX_MOVE(__a);
+      __a = _GLIBCXX_MOVE(__b);
+      __b = _GLIBCXX_MOVE(__tmp);
+    }
+
+#if __cplusplus >= 201103L
+   namespace __is_swappable_impl {
+     template <typename _Tp, typename=void>
+     struct __is_swappable : public false_type
+     { };
+   }
+#endif
+
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // DR 809. std::swap should be overloaded for array types.
+  /// Swap the contents of two arrays.
+  template<typename _Tp, size_t _Nm>
+    inline
+#if __cplusplus >= 201103L
+    typename enable_if<__is_swappable_impl::__is_swappable<_Tp>::value>::type
+#else
+    void
+#endif
+    swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
+#if __cplusplus >= 201103L
+    noexcept(noexcept(swap(*__a, *__b)))
+#endif
+    {
+      for (size_t __n = 0; __n < _Nm; ++__n)
+	swap(__a[__n], __b[__n]);
+    }
+
+#if __cplusplus >= 201103L
+  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>
+    { };
+#endif
+
+  /// @} group utilities
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
 #endif  // _GLIBCXX_TYPE_TRAITS
diff --git a/libstdc++-v3/testsuite/20_util/forward/c_neg.cc b/libstdc++-v3/testsuite/20_util/forward/c_neg.cc
index ca1c9c5..235338a 100644
--- a/libstdc++-v3/testsuite/20_util/forward/c_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/forward/c_neg.cc
@@ -18,7 +18,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-error "static assertion failed" "" { target *-*-* } 89 }
+// { dg-error "static assertion failed" "" { target *-*-* } 2482 }
 
 #include <list>
 
diff --git a/libstdc++-v3/testsuite/20_util/forward/f_neg.cc b/libstdc++-v3/testsuite/20_util/forward/f_neg.cc
index 971168a..eada1b3 100644
--- a/libstdc++-v3/testsuite/20_util/forward/f_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/forward/f_neg.cc
@@ -18,7 +18,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-error "static assertion failed" "" { target *-*-* } 89 }
+// { dg-error "static assertion failed" "" { target *-*-* } 2482 }
 
 #include <utility>
 
diff --git a/libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc b/libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc
deleted file mode 100644
index 8452b75..0000000
--- a/libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// { dg-do compile }
-// { dg-options "-std=gnu++98" }
-
-// Copyright (C) 2007-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>
-
-// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
-
-
-
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
index 0000000..93fa94b
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc
@@ -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
index 0000000..2372349
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc
@@ -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
index 0000000..bc778b5
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc
@@ -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), "");
+}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [libstdc++ PATCH] Implement __is_nothrow_swappable and use it
  2015-05-01  9:47 [libstdc++ PATCH] Implement __is_nothrow_swappable and use it Ville Voutilainen
@ 2015-05-01  9:55 ` Ville Voutilainen
  2015-06-05 14:58 ` Jonathan Wakely
  1 sibling, 0 replies; 3+ messages in thread
From: Ville Voutilainen @ 2015-05-01  9:55 UTC (permalink / raw)
  To: gcc-patches, libstdc++

On 1 May 2015 at 12:47, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
> This patch partially solves the problem described in N4426, which is
> basically LWG
> issue 2456, which in turn is caused by CWG DR 1330. Some remarks:

..and I forgot to mention that it fixes PR 63860.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [libstdc++ PATCH] Implement __is_nothrow_swappable and use it
  2015-05-01  9:47 [libstdc++ PATCH] Implement __is_nothrow_swappable and use it Ville Voutilainen
  2015-05-01  9:55 ` Ville Voutilainen
@ 2015-06-05 14:58 ` Jonathan Wakely
  1 sibling, 0 replies; 3+ messages in thread
From: Jonathan Wakely @ 2015-06-05 14:58 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 1021 bytes --]

On 01/05/15 12:47 +0300, Ville Voutilainen wrote:
>This patch partially solves the problem described in N4426, which is
>basically LWG
>issue 2456, which in turn is caused by CWG DR 1330. Some remarks:
>- the __is_swappable and __is_nothrow_swappable are at this time not
>meant to be general traits, they make the shortcut of automatically transforming
>their template parameter into a reference, which the truly general trait
>as described in N4426 wouldn't do.
>- swap is now constrained..
>- ..which means that everything from bits/move.h moves to type_traits since
>swap now needs type_traits. type_traits becomes ok to include in pre-c++14
>modes, but only enables the parts that work in pre-c++14 modes.
>- this patch does _not_ yet implement N4426.

I've committed this slightly altered patch, which doesn't move swap
into <type_traits> but just declares it there. The definition remains
in <bits/move.h> and including <type_traits> in c++98 mode is still
an error.

Tested powerpc64le-linux, committed to trunk.

[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 15872 bytes --]

commit d485df2eebd2869b3a17a3d67b2a394dbbbedab9
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Jun 5 13:20:53 2015 +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.

diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h
index 1dfc4ad..c972f33 100644
--- a/libstdc++-v3/include/bits/algorithmfwd.h
+++ b/libstdc++-v3/include/bits/algorithmfwd.h
@@ -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 
diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h
index 1dfd667..88c4f7b 100644
--- a/libstdc++-v3/include/bits/move.h
+++ b/libstdc++-v3/include/bits/move.h
@@ -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)
diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index 3daeb60..490b005 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -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);
diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h
index 48e1ee7..5f8e6fb 100644
--- a/libstdc++-v3/include/bits/stl_queue.h
+++ b/libstdc++-v3/include/bits/stl_queue.h
@@ -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);
diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h
index 3ff307f..0ed212e 100644
--- a/libstdc++-v3/include/bits/stl_stack.h
+++ b/libstdc++-v3/include/bits/stl_stack.h
@@ -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);
diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array
index 7bb74c1..34e6281 100644
--- a/libstdc++-v3/include/debug/array
+++ b/libstdc++-v3/include/debug/array
@@ -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.
diff --git a/libstdc++-v3/include/profile/array b/libstdc++-v3/include/profile/array
index 5198bb3..434ca96 100644
--- a/libstdc++-v3/include/profile/array
+++ b/libstdc++-v3/include/profile/array
@@ -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.
diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index 24be44f..40fbd46 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -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.
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index ad132bd..ccea02b 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -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));
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index b8ec61f..2eae61b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -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
index 0000000..93fa94b
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc
@@ -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
index 0000000..2372349
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc
@@ -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
index 0000000..bc778b5
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc
@@ -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), "");
+}

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-06-05 14:44 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-01  9:47 [libstdc++ PATCH] Implement __is_nothrow_swappable and use it Ville Voutilainen
2015-05-01  9:55 ` Ville Voutilainen
2015-06-05 14:58 ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).