EricWF created this revision.
EricWF added reviewers: mclow.lists, rsmith, K-ballo.
EricWF added a subscriber: cfe-commits.

This shows the basic jist of my proposed changes. I haven't tested them enough 
to ensure they are 100% correct.

Can anybody suggest a better solution?

http://reviews.llvm.org/D21314

Files:
  include/utility
  test/test.pass.cpp

Index: test/test.pass.cpp
===================================================================
--- /dev/null
+++ test/test.pass.cpp
@@ -0,0 +1,54 @@
+#include <utility>
+#include <tuple>
+#include <type_traits>
+#include <memory>
+
+struct NonAssignable {
+  NonAssignable& operator=(NonAssignable const&) = delete;
+  NonAssignable& operator=(NonAssignable&&) = delete;
+
+};
+
+int main() {
+    using Ptr = std::unique_ptr<int>;
+    using NA = NonAssignable;
+    {
+        using T = std::pair<int, Ptr>;
+        static_assert(!std::is_copy_assignable<T>::value, "");
+        static_assert(std::is_move_assignable<T>::value, "");
+    }
+    {
+        using T = std::pair<int, Ptr&>;
+        static_assert(!std::is_copy_assignable<T>::value, "");
+        static_assert(std::is_move_assignable<T>::value, "");
+    }
+    {
+        using T = std::pair<int, Ptr&&>;
+        static_assert(!std::is_copy_assignable<T>::value, "");
+        static_assert(std::is_move_assignable<T>::value, "");
+    }
+    {
+        using T = std::pair<int, Ptr const&>;
+        static_assert(!std::is_copy_assignable<T>::value, "");
+        static_assert(!std::is_move_assignable<T>::value, "");
+    }
+    {
+        using T = std::pair<int&, int&&>;
+        static_assert(std::is_copy_assignable<T>::value, "");
+        static_assert(std::is_move_assignable<T>::value, "");
+    }
+    {
+        using T = std::tuple<int, Ptr>;
+        static_assert(!std::is_copy_assignable<T>::value, "");
+    }
+    {
+        using T = std::pair<int, NA>;
+        static_assert(!std::is_copy_assignable<T>::value, "");
+        static_assert(!std::is_move_assignable<T>::value, "");
+    }
+    {
+        using T = std::tuple<int, NA>;
+        static_assert(!std::is_copy_assignable<T>::value, "");
+        static_assert(!std::is_move_assignable<T>::value, "");
+    }
+}
\ No newline at end of file
Index: include/utility
===================================================================
--- include/utility
+++ include/utility
@@ -276,6 +276,7 @@
 constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t();
 #endif
 
+
 template <class _T1, class _T2>
 struct _LIBCPP_TYPE_VIS_ONLY pair
 {
@@ -323,11 +324,20 @@
     {
     }
 #endif
+    typedef typename remove_reference<_T1>::type _T1Unref;
+    typedef typename remove_reference<_T2>::type _T2Unref;
+
+    typedef integral_constant<bool,
+        (is_reference<_T1>::value || is_reference<_T2>::value)
+        && is_copy_assignable<_T1Unref>::value
+        && is_copy_assignable<_T2Unref>::value> _CanCopyAssign;
+
 
     _LIBCPP_INLINE_VISIBILITY
-    pair& operator=(const pair& __p)
-        _NOEXCEPT_(is_nothrow_copy_assignable<first_type>::value &&
-                   is_nothrow_copy_assignable<second_type>::value)
+    pair&
+    operator=(typename conditional<_CanCopyAssign::value == true, pair const&, __nat&>::type __p)
+        _NOEXCEPT_(is_nothrow_copy_assignable<_T1Unref>::value &&
+                   is_nothrow_copy_assignable<_T2Unref>::value)
     {
         first = __p.first;
         second = __p.second;
@@ -365,11 +375,16 @@
     {
     }
 #endif
+    typedef integral_constant<bool,
+        (is_reference<_T1>::value || is_reference<_T2>::value)
+        && is_move_assignable<_T1Unref>::value
+        && is_move_assignable<_T2Unref>::value> _CanMoveAssign;
 
     _LIBCPP_INLINE_VISIBILITY
     pair&
-    operator=(pair&& __p) _NOEXCEPT_(is_nothrow_move_assignable<first_type>::value &&
-                                     is_nothrow_move_assignable<second_type>::value)
+    operator=(typename conditional<_CanMoveAssign::value, pair&&, __nat&&>::type __p)
+                          _NOEXCEPT_(is_nothrow_move_assignable<_T1Unref>::value &&
+                                     is_nothrow_move_assignable<_T2Unref>::value)
     {
         first = _VSTD::forward<first_type>(__p.first);
         second = _VSTD::forward<second_type>(__p.second);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to