EricWF retitled this revision from "Make pair respect is_copy_assignable and 
is_move_assignable" to "Make pair and tuple respect is_copy_assignable and 
is_move_assignable".
EricWF updated this revision to Diff 60631.
EricWF added a comment.



- Remove `= default` copy/move constructors in pair. Let the compiler 
implicitly mark them as default.
- Roughly implement the changes in `<tuple>` This still needs a ton more tests.


http://reviews.llvm.org/D21314

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

Index: test/test.pass.cpp
===================================================================
--- /dev/null
+++ test/test.pass.cpp
@@ -0,0 +1,68 @@
+#include <utility>
+#include <tuple>
+#include <type_traits>
+#include <memory>
+
+#include "test_macros.h"
+
+struct NonAssignable {
+private:
+  NonAssignable& operator=(NonAssignable const&) _LIBCPP_EQUAL_DELETE;
+#if TEST_STD_VER >= 11
+  NonAssignable& operator=(NonAssignable&&) _LIBCPP_EQUAL_DELETE;
+#endif
+};
+
+int main() {
+    typedef std::unique_ptr<int> Ptr;
+    typedef NonAssignable NA;
+    {
+        typedef std::pair<int, int> T;
+        const T x(1, 2);
+        T y;
+        y = x;
+        static_assert(std::is_copy_assignable<T>::value, "");
+        static_assert(std::is_move_assignable<T>::value, "");
+    }
+#if TEST_STD_VER >= 11
+    {
+        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, "");
+    }
+#endif
+}
\ 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
 {
@@ -310,10 +311,7 @@
                                       )
             : first(__p.first), second(__p.second) {}
 
-#if !defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && _LIBCPP_TRIVIAL_PAIR_COPY_CTOR
-    _LIBCPP_INLINE_VISIBILITY
-    pair(const pair& __p) = default;
-#elif !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) || !_LIBCPP_TRIVIAL_PAIR_COPY_CTOR
+#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) || !_LIBCPP_TRIVIAL_PAIR_COPY_CTOR
     _LIBCPP_INLINE_VISIBILITY
     pair(const pair& __p)
         _NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value &&
@@ -323,11 +321,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;
@@ -353,23 +360,25 @@
             : first(_VSTD::forward<_U1>(__p.first)),
               second(_VSTD::forward<_U2>(__p.second)) {}
 
-#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
-    _LIBCPP_INLINE_VISIBILITY
-    pair(pair&& __p) = default;
-#else
+#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
     _LIBCPP_INLINE_VISIBILITY
     pair(pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<first_type>::value &&
                                 is_nothrow_move_constructible<second_type>::value)
         : first(_VSTD::forward<first_type>(__p.first)),
           second(_VSTD::forward<second_type>(__p.second))
     {
     }
 #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);
Index: include/tuple
===================================================================
--- include/tuple
+++ include/tuple
@@ -184,7 +184,6 @@
 {
     _Hp value;
 
-    __tuple_leaf& operator=(const __tuple_leaf&);
 public:
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __tuple_leaf()
              _NOEXCEPT_(is_nothrow_default_constructible<_Hp>::value) : value()
@@ -280,6 +279,25 @@
     __tuple_leaf(const __tuple_leaf& __t) = default;
     __tuple_leaf(__tuple_leaf&& __t) = default;
 
+    using _HpUnref = typename remove_reference<_Hp>::type;
+    using _CanCopyAssign = integral_constant<bool,
+        is_reference<_Hp>::value && is_copy_assignable<_HpUnref>::value>;
+    using _CanMoveAssign = integral_constant<bool,
+        is_reference<_Hp>::value && is_move_assignable<_HpUnref>::value>;
+#if 1
+    __tuple_leaf&
+    operator=(typename conditional<_CanCopyAssign::value, __tuple_leaf const&, __nat&>::type __v) {
+        value = __v.value;
+        return *this;
+    }
+
+     __tuple_leaf&
+    operator=(typename conditional<_CanMoveAssign::value, __tuple_leaf&&, __nat&&>::type __v) {
+        value = _VSTD::move(__v.value);
+        return *this;
+    }
+#endif
+
     template <class _Tp>
         _LIBCPP_INLINE_VISIBILITY
         __tuple_leaf&
@@ -356,7 +374,7 @@
 
     template <class _Tp>
         _LIBCPP_INLINE_VISIBILITY
-        __tuple_leaf&
+        typename enable_if<!is_same<typename decay<_Tp>::type, __tuple_leaf>::value, __tuple_leaf&>::type
         operator=(_Tp&& __t) _NOEXCEPT_((is_nothrow_assignable<_Hp&, _Tp>::value))
         {
             _Hp::operator=(_VSTD::forward<_Tp>(__t));
@@ -477,22 +495,9 @@
 
     __tuple_impl(const __tuple_impl&) = default;
     __tuple_impl(__tuple_impl&&) = default;
+    __tuple_impl& operator=(__tuple_impl const&) = default;
+    __tuple_impl& operator=(__tuple_impl &&) = default;
 
-    _LIBCPP_INLINE_VISIBILITY
-    __tuple_impl&
-    operator=(const __tuple_impl& __t) _NOEXCEPT_((__all<is_nothrow_copy_assignable<_Tp>::value...>::value))
-    {
-        __swallow(__tuple_leaf<_Indx, _Tp>::operator=(static_cast<const __tuple_leaf<_Indx, _Tp>&>(__t).get())...);
-        return *this;
-    }
-
-    _LIBCPP_INLINE_VISIBILITY
-    __tuple_impl&
-    operator=(__tuple_impl&& __t) _NOEXCEPT_((__all<is_nothrow_move_assignable<_Tp>::value...>::value))
-    {
-        __swallow(__tuple_leaf<_Indx, _Tp>::operator=(_VSTD::forward<_Tp>(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t).get()))...);
-        return *this;
-    }
 
     _LIBCPP_INLINE_VISIBILITY
     void swap(__tuple_impl& __t)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to