[libcxx] r275094 - Allow is_swappable to SFINAE on deleted/ambiguous swap functions

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 11 12:57:13 PDT 2016


Author: ericwf
Date: Mon Jul 11 14:57:13 2016
New Revision: 275094

URL: http://llvm.org/viewvc/llvm-project?rev=275094&view=rev
Log:
Allow is_swappable to SFINAE on deleted/ambiguous swap functions

Modified:
    libcxx/trunk/include/type_traits
    libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp

Modified: libcxx/trunk/include/type_traits
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=275094&r1=275093&r2=275094&view=diff
==============================================================================
--- libcxx/trunk/include/type_traits (original)
+++ libcxx/trunk/include/type_traits Mon Jul 11 14:57:13 2016
@@ -4446,15 +4446,20 @@ iter_swap(_ForwardIterator1 __a, _Forwar
 namespace __detail
 {
 // ALL generic swap overloads MUST already have a declaration available at this point.
-using _VSTD::swap;
-__nat swap(__any, __any);
 
 template <class _Tp, class _Up = _Tp,
           bool _NotVoid = !is_void<_Tp>::value && !is_void<_Up>::value>
 struct __swappable_with
 {
-    typedef decltype(swap(_VSTD::declval<_Tp>(), _VSTD::declval<_Up>())) __swap1;
-    typedef decltype(swap(_VSTD::declval<_Up>(), _VSTD::declval<_Tp>())) __swap2;
+    template <class _LHS, class _RHS>
+    static decltype(swap(_VSTD::declval<_LHS>(), _VSTD::declval<_RHS>()))
+    __test_swap(int);
+    template <class, class>
+    static __nat __test_swap(long);
+
+    // Extra parens are needed for the C++03 definition of decltype.
+    typedef decltype((__test_swap<_Tp, _Up>(0))) __swap1;
+    typedef decltype((__test_swap<_Up, _Tp>(0))) __swap2;
 
     static const bool value = !is_same<__swap1, __nat>::value
                            && !is_same<__swap2, __nat>::value;

Modified: libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp?rev=275094&r1=275093&r2=275094&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp Mon Jul 11 14:57:13 2016
@@ -49,8 +49,21 @@ struct M {
 
 void swap(M&&, M&&) {}
 
+struct DeletedSwap {
+  friend void swap(DeletedSwap&, DeletedSwap&) = delete;
+};
+
 } // namespace MyNS
 
+namespace MyNS2 {
+
+struct AmbiguousSwap {};
+
+template <class T>
+void swap(T&, T&) {}
+
+} // end namespace MyNS2
+
 int main()
 {
     using namespace MyNS;
@@ -70,6 +83,14 @@ int main()
         static_assert(!std::is_swappable<int() &>::value, "");
     }
     {
+        // test that a deleted swap is correctly handled.
+        static_assert(!std::is_swappable<DeletedSwap>::value, "");
+    }
+    {
+        // test that a swap with ambiguous overloads is handled correctly.
+        static_assert(!std::is_swappable<MyNS2::AmbiguousSwap>::value, "");
+    }
+    {
         // test for presence of is_swappable_v
         static_assert(std::is_swappable_v<int>, "");
         static_assert(!std::is_swappable_v<M>, "");




More information about the cfe-commits mailing list