Revert r276548 - Make pair/tuples assignment operators SFINAE properly.
authorEric Fiselier <eric@efcs.ca>
Mon, 25 Jul 2016 01:45:07 +0000 (01:45 +0000)
committerEric Fiselier <eric@efcs.ca>
Mon, 25 Jul 2016 01:45:07 +0000 (01:45 +0000)
This is a breaking change. The SFINAE required is instantiated the second
the class is instantiated, and this can cause hard SFINAE errors
when applied to references to incomplete types. Ex.

struct IncompleteType;
extern IncompleteType it;
std::tuple<IncompleteType&> t(it); // SFINAE will blow up.

llvm-svn: 276598

libcxx/include/tuple
libcxx/include/utility
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp [deleted file]
libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair_cxx03.pass.cpp [deleted file]
libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp

index a68f115..31613d2 100644 (file)
@@ -647,9 +647,6 @@ public:
     _LIBCPP_CONSTEXPR tuple()
         _NOEXCEPT_(__all<is_nothrow_default_constructible<_Tp>::value...>::value) {}
 
-    tuple(tuple const&) = default;
-    tuple(tuple&&) = default;
-
     template <class _AllocArgT, class _Alloc, bool _Dummy = true, class = typename enable_if<
         __lazy_and<
             is_same<allocator_arg_t, _AllocArgT>,
@@ -888,25 +885,6 @@ public:
         tuple(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
             : base_(allocator_arg_t(), __a, _VSTD::forward<_Tuple>(__t)) {}
 
-    using _CanCopyAssign = __all<is_copy_assignable<_Tp>::value...>;
-    using _CanMoveAssign = __all<is_move_assignable<_Tp>::value...>;
-
-    _LIBCPP_INLINE_VISIBILITY
-    tuple& operator=(typename conditional<_CanCopyAssign::value, tuple, __nat>::type const& __t)
-        _NOEXCEPT_((__all<is_nothrow_copy_assignable<_Tp>::value...>::value))
-    {
-        base_.operator=(__t.base_);
-        return *this;
-    }
-
-    _LIBCPP_INLINE_VISIBILITY
-    tuple& operator=(typename conditional<_CanMoveAssign::value, tuple, __nat>::type&& __t)
-        _NOEXCEPT_((__all<is_nothrow_move_assignable<_Tp>::value...>::value))
-    {
-        base_.operator=(static_cast<base&&>(__t.base_));
-        return *this;
-    }
-
     template <class _Tuple,
               class = typename enable_if
                       <
index 9a155a0..022a641 100644 (file)
@@ -348,19 +348,8 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
   // Use the implicitly declared copy constructor in C++03
 #endif
 
-    typedef typename remove_reference<_T1>::type _T1Unref;
-    typedef typename remove_reference<_T2>::type _T2Unref;
-
-#if !defined(_LIBCPP_CXX03_LANG)
-    typedef integral_constant<bool,
-           is_copy_assignable<_T1>::value
-        && is_copy_assignable<_T2>::value> _CanCopyAssign;
-#else
-    typedef true_type _CanCopyAssign;
-#endif
-
     _LIBCPP_INLINE_VISIBILITY
-    pair& operator=(typename conditional<_CanCopyAssign::value, pair, __nat>::type const& __p)
+    pair& operator=(const pair& __p)
         _NOEXCEPT_(is_nothrow_copy_assignable<first_type>::value &&
                    is_nothrow_copy_assignable<second_type>::value)
     {
@@ -388,15 +377,10 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
             : first(_VSTD::forward<_U1>(__p.first)),
               second(_VSTD::forward<_U2>(__p.second)) {}
 
-    typedef integral_constant<bool,
-           is_move_assignable<_T1>::value
-        && is_move_assignable<_T2>::value> _CanMoveAssign;
-
     _LIBCPP_INLINE_VISIBILITY
     pair&
-    operator=(typename conditional<_CanMoveAssign::value, pair, __nat>::type&& __p)
-        _NOEXCEPT_(is_nothrow_move_assignable<first_type>::value &&
-                   is_nothrow_move_assignable<second_type>::value)
+    operator=(pair&& __p) _NOEXCEPT_(is_nothrow_move_assignable<first_type>::value &&
+                                     is_nothrow_move_assignable<second_type>::value)
     {
         first = _VSTD::forward<first_type>(__p.first);
         second = _VSTD::forward<second_type>(__p.second);
@@ -404,6 +388,7 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
     }
 
 #ifndef _LIBCPP_HAS_NO_VARIADICS
+
     template<class _Tuple,
              class = typename enable_if<__tuple_convertible<_Tuple, pair>::value>::type>
         _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
@@ -426,7 +411,7 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
             {}
 
     template <class _Tuple,
-              class = typename enable_if<!is_same<typename decay<_Tuple>::type, pair>::value && __tuple_assignable<_Tuple, pair>::value>::type>
+              class = typename enable_if<__tuple_assignable<_Tuple, pair>::value>::type>
         _LIBCPP_INLINE_VISIBILITY
         pair&
         operator=(_Tuple&& __p)
index 6a24c27..d5d0207 100644 (file)
 #include <string>
 #include <cassert>
 
-#include "test_macros.h"
-
-struct NonAssignable {
-  NonAssignable& operator=(NonAssignable const&) = delete;
-  NonAssignable& operator=(NonAssignable&&) = delete;
-};
-struct CopyAssignable {
-  CopyAssignable& operator=(CopyAssignable const&) = default;
-  CopyAssignable& operator=(CopyAssignable &&) = delete;
-};
-static_assert(std::is_copy_assignable<CopyAssignable>::value, "");
-struct MoveAssignable {
-  MoveAssignable& operator=(MoveAssignable const&) = delete;
-  MoveAssignable& operator=(MoveAssignable&&) = default;
-};
-
 int main()
 {
     {
@@ -67,37 +51,4 @@ int main()
         assert(std::get<1>(t) == 'a');
         assert(std::get<2>(t) == "some text");
     }
-    {
-        // test reference assignment.
-        using T = std::tuple<int&, int&&>;
-        int x = 42;
-        int y = 100;
-        int x2 = -1;
-        int y2 = 500;
-        T t(x, std::move(y));
-        T t2(x2, std::move(y2));
-        t = t2;
-        assert(std::get<0>(t) == x2);
-        assert(&std::get<0>(t) == &x);
-        assert(std::get<1>(t) == y2);
-        assert(&std::get<1>(t) == &y);
-    }
-    {
-        // test that the implicitly generated copy assignment operator
-        // is properly deleted
-        using T = std::tuple<std::unique_ptr<int>>;
-        static_assert(!std::is_copy_assignable<T>::value, "");
-    }
-    {
-        using T = std::tuple<int, NonAssignable>;
-        static_assert(!std::is_copy_assignable<T>::value, "");
-    }
-    {
-        using T = std::tuple<int, CopyAssignable>;
-        static_assert(std::is_copy_assignable<T>::value, "");
-    }
-    {
-        using T = std::tuple<int, MoveAssignable>;
-        static_assert(!std::is_copy_assignable<T>::value, "");
-    }
 }
index 210f14b..fc5e41a 100644 (file)
 
 #include "MoveOnly.h"
 
-struct NonAssignable {
-  NonAssignable& operator=(NonAssignable const&) = delete;
-  NonAssignable& operator=(NonAssignable&&) = delete;
-};
-struct CopyAssignable {
-  CopyAssignable& operator=(CopyAssignable const&) = default;
-  CopyAssignable& operator=(CopyAssignable&&) = delete;
-};
-static_assert(std::is_copy_assignable<CopyAssignable>::value, "");
-struct MoveAssignable {
-  MoveAssignable& operator=(MoveAssignable const&) = delete;
-  MoveAssignable& operator=(MoveAssignable&&) = default;
-};
-
-
-struct CountAssign {
-  static int copied;
-  static int moved;
-  static void reset() { copied = moved = 0; }
-  CountAssign() = default;
-  CountAssign& operator=(CountAssign const&) { ++copied; return *this; }
-  CountAssign& operator=(CountAssign&&) { ++moved; return *this; }
-};
-int CountAssign::copied = 0;
-int CountAssign::moved = 0;
-
-
 int main()
 {
     {
@@ -80,46 +53,4 @@ int main()
         assert(std::get<1>(t) == 1);
         assert(std::get<2>(t) == 2);
     }
-    {
-        // test reference assignment.
-        using T = std::tuple<int&, int&&>;
-        int x = 42;
-        int y = 100;
-        int x2 = -1;
-        int y2 = 500;
-        T t(x, std::move(y));
-        T t2(x2, std::move(y2));
-        t = std::move(t2);
-        assert(std::get<0>(t) == x2);
-        assert(&std::get<0>(t) == &x);
-        assert(std::get<1>(t) == y2);
-        assert(&std::get<1>(t) == &y);
-    }
-    {
-        // test that the implicitly generated move assignment operator
-        // is properly deleted
-        using T = std::tuple<std::unique_ptr<int>>;
-        static_assert(std::is_move_assignable<T>::value, "");
-        static_assert(!std::is_copy_assignable<T>::value, "");
-
-    }
-    {
-        using T = std::tuple<int, NonAssignable>;
-        static_assert(!std::is_move_assignable<T>::value, "");
-    }
-    {
-        using T = std::tuple<int, MoveAssignable>;
-        static_assert(std::is_move_assignable<T>::value, "");
-    }
-    {
-        // The move should decay to a copy.
-        CountAssign::reset();
-        using T = std::tuple<CountAssign, CopyAssignable>;
-        static_assert(std::is_move_assignable<T>::value, "");
-        T t1;
-        T t2;
-        t1 = std::move(t2);
-        assert(CountAssign::copied == 1);
-        assert(CountAssign::moved == 0);
-    }
 }
diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp
deleted file mode 100644 (file)
index d75b6a5..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <utility>
-
-// template <class T1, class T2> struct pair
-
-// pair& operator=(pair const& p);
-
-#include <utility>
-#include <memory>
-#include <cassert>
-
-
-struct NonAssignable {
-  NonAssignable& operator=(NonAssignable const&) = delete;
-  NonAssignable& operator=(NonAssignable&&) = delete;
-};
-struct CopyAssignable {
-  CopyAssignable() = default;
-  CopyAssignable(CopyAssignable const&) = default;
-  CopyAssignable& operator=(CopyAssignable const&) = default;
-  CopyAssignable& operator=(CopyAssignable&&) = delete;
-};
-struct MoveAssignable {
-  MoveAssignable() = default;
-  MoveAssignable& operator=(MoveAssignable const&) = delete;
-  MoveAssignable& operator=(MoveAssignable&&) = default;
-};
-
-
-struct CountAssign {
-  static int copied;
-  static int moved;
-  static void reset() { copied = moved = 0; }
-  CountAssign() = default;
-  CountAssign& operator=(CountAssign const&) { ++copied; return *this; }
-  CountAssign& operator=(CountAssign&&) { ++moved; return *this; }
-};
-int CountAssign::copied = 0;
-int CountAssign::moved = 0;
-
-int main()
-{
-    {
-        typedef std::pair<CopyAssignable, short> P;
-        const P p1(CopyAssignable(), 4);
-        P p2;
-        p2 = p1;
-        assert(p2.second == 4);
-    }
-    {
-        using P = std::pair<int&, int&&>;
-        int x = 42;
-        int y = 101;
-        int x2 = -1;
-        int y2 = 300;
-        P p1(x, std::move(y));
-        P p2(x2, std::move(y2));
-        p1 = p2;
-        assert(p1.first == x2);
-        assert(p1.second == y2);
-    }
-    {
-        using P = std::pair<int, NonAssignable>;
-        static_assert(!std::is_copy_assignable<P>::value, "");
-    }
-    {
-        CountAssign::reset();
-        using P = std::pair<CountAssign, CopyAssignable>;
-        static_assert(std::is_copy_assignable<P>::value, "");
-        P p;
-        P p2;
-        p = p2;
-        assert(CountAssign::copied == 1);
-        assert(CountAssign::moved == 0);
-    }
-    {
-        using P = std::pair<int, MoveAssignable>;
-        static_assert(!std::is_copy_assignable<P>::value, "");
-    }
-}
diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair_cxx03.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair_cxx03.pass.cpp
deleted file mode 100644 (file)
index 8b9d1ed..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES-ANY: c++98, c++03
-
-// <utility>
-
-// template <class T1, class T2> struct pair
-
-// pair& operator=(pair const& p);
-
-#include <utility>
-#include <memory>
-#include <cassert>
-
-
-struct NonAssignable {
-  NonAssignable() {}
-private:
-  NonAssignable& operator=(NonAssignable const&);
-};
-
-int main()
-{
-    // Test that we don't constrain the assignment operator in C++03 mode.
-    // Since we don't have access control SFINAE having pair evaluate SFINAE
-    // may cause a hard error.
-    typedef std::pair<int, NonAssignable> P;
-    static_assert(std::is_copy_assignable<P>::value, "");
-}
index 3808920..a753ee5 100644 (file)
@@ -7,8 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++98, c++03
-
 // <utility>
 
 // template <class T1, class T2> struct pair
 #include <memory>
 #include <cassert>
 
-
-struct NonAssignable {
-  NonAssignable& operator=(NonAssignable const&) = delete;
-  NonAssignable& operator=(NonAssignable&&) = delete;
-};
-struct CopyAssignable {
-  CopyAssignable() = default;
-  CopyAssignable& operator=(CopyAssignable const&) = default;
-  CopyAssignable& operator=(CopyAssignable&&) = delete;
-};
-struct MoveAssignable {
-  MoveAssignable() = default;
-  MoveAssignable& operator=(MoveAssignable const&) = delete;
-  MoveAssignable& operator=(MoveAssignable&&) = default;
-};
-
-struct CountAssign {
-  static int copied;
-  static int moved;
-  static void reset() { copied = moved = 0; }
-  CountAssign() = default;
-  CountAssign& operator=(CountAssign const&) { ++copied; return *this; }
-  CountAssign& operator=(CountAssign&&) { ++moved; return *this; }
-};
-int CountAssign::copied = 0;
-int CountAssign::moved = 0;
-
 int main()
 {
+#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     {
         typedef std::pair<std::unique_ptr<int>, short> P;
         P p1(std::unique_ptr<int>(new int(3)), 4);
@@ -56,41 +28,5 @@ int main()
         assert(*p2.first == 3);
         assert(p2.second == 4);
     }
-    {
-        using P = std::pair<int&, int&&>;
-        int x = 42;
-        int y = 101;
-        int x2 = -1;
-        int y2 = 300;
-        P p1(x, std::move(y));
-        P p2(x2, std::move(y2));
-        p1 = std::move(p2);
-        assert(p1.first == x2);
-        assert(p1.second == y2);
-    }
-    {
-        using P = std::pair<int, NonAssignable>;
-        static_assert(!std::is_move_assignable<P>::value, "");
-    }
-    {
-        // The move decays to the copy constructor
-        CountAssign::reset();
-        using P = std::pair<CountAssign, CopyAssignable>;
-        static_assert(std::is_move_assignable<P>::value, "");
-        P p;
-        P p2;
-        p = std::move(p2);
-        assert(CountAssign::moved == 0);
-        assert(CountAssign::copied == 1);
-    }
-    {
-        CountAssign::reset();
-        using P = std::pair<CountAssign, MoveAssignable>;
-        static_assert(std::is_move_assignable<P>::value, "");
-        P p;
-        P p2;
-        p = std::move(p2);
-        assert(CountAssign::moved == 1);
-        assert(CountAssign::copied == 0);
-    }
+#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 }