[libcxx] r279953 - Fix pair::operator=(TupleLike&&).

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Sun Aug 28 18:09:47 PDT 2016


Author: ericwf
Date: Sun Aug 28 20:09:47 2016
New Revision: 279953

URL: http://llvm.org/viewvc/llvm-project?rev=279953&view=rev
Log:
Fix pair::operator=(TupleLike&&).

This assignment operator was previously broken since the SFINAE always resulted
in substitution failure. This caused assignments to turn into
copy construction + assignment.

Added:
    libcxx/trunk/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp
Modified:
    libcxx/trunk/include/utility

Modified: libcxx/trunk/include/utility
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?rev=279953&r1=279952&r2=279953&view=diff
==============================================================================
--- libcxx/trunk/include/utility (original)
+++ libcxx/trunk/include/utility Sun Aug 28 20:09:47 2016
@@ -515,7 +515,7 @@ struct _LIBCPP_TYPE_VIS_ONLY pair
     }
 
     template <class _Tuple, _EnableB<
-            _CheckTLC<_Tuple>::template __enable_assign()
+            _CheckTLC<_Tuple>::template __enable_assign<_Tuple>()
      > = false>
     _LIBCPP_INLINE_VISIBILITY
     pair& operator=(_Tuple&& __p) {

Added: libcxx/trunk/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp?rev=279953&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp Sun Aug 28 20:09:47 2016
@@ -0,0 +1,135 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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
+
+// template<class U, class V> pair& operator=(tuple<U, V>&& p);
+
+#include <utility>
+#include <tuple>
+#include <array>
+#include <memory>
+#include <cassert>
+
+struct CountingType {
+  static int constructed;
+  static int copy_constructed;
+  static int move_constructed;
+  static int assigned;
+  static int copy_assigned;
+  static int move_assigned;
+  static void reset() {
+      constructed = copy_constructed = move_constructed = 0;
+      assigned = copy_assigned = move_assigned = 0;
+  }
+  CountingType() : value(0) { ++constructed; }
+  CountingType(int v) : value(v) { ++constructed; }
+  CountingType(CountingType const& o) : value(o.value) { ++constructed; ++copy_constructed; }
+  CountingType(CountingType&& o) : value(o.value) { ++constructed; ++move_constructed; o.value = -1;}
+
+  CountingType& operator=(CountingType const& o) {
+      ++assigned;
+      ++copy_assigned;
+      value = o.value;
+      return *this;
+  }
+  CountingType& operator=(CountingType&& o) {
+      ++assigned;
+      ++move_assigned;
+      value = o.value;
+      o.value = -1;
+      return *this;
+  }
+  int value;
+};
+int CountingType::constructed;
+int CountingType::copy_constructed;
+int CountingType::move_constructed;
+int CountingType::assigned;
+int CountingType::copy_assigned;
+int CountingType::move_assigned;
+
+int main()
+{
+    using C = CountingType;
+    {
+       using P = std::pair<int, C>;
+       using T = std::tuple<int, C>;
+       T t(42, C{42});
+       P p(101, C{101});
+       C::reset();
+       p = t;
+       assert(C::constructed == 0);
+       assert(C::assigned == 1);
+       assert(C::copy_assigned == 1);
+       assert(C::move_assigned == 0);
+       assert(p.first == 42);
+       assert(p.second.value == 42);
+    }
+    {
+       using P = std::pair<int, C>;
+       using T = std::tuple<int, C>;
+       T t(42, -42);
+       P p(101, 101);
+       C::reset();
+       p = std::move(t);
+       assert(C::constructed == 0);
+       assert(C::assigned == 1);
+       assert(C::copy_assigned == 0);
+       assert(C::move_assigned == 1);
+       assert(p.first == 42);
+       assert(p.second.value == -42);
+    }
+    {
+       using P = std::pair<C, C>;
+       using T = std::array<C, 2>;
+       T t = {42, -42};
+       P p{101, 101};
+       C::reset();
+       p = t;
+       assert(C::constructed == 0);
+       assert(C::assigned == 2);
+       assert(C::copy_assigned == 2);
+       assert(C::move_assigned == 0);
+       assert(p.first.value == 42);
+       assert(p.second.value == -42);
+    }
+    {
+       using P = std::pair<C, C>;
+       using T = std::array<C, 2>;
+       T t = {42, -42};
+       P p{101, 101};
+       C::reset();
+       p = t;
+       assert(C::constructed == 0);
+       assert(C::assigned == 2);
+       assert(C::copy_assigned == 2);
+       assert(C::move_assigned == 0);
+       assert(p.first.value == 42);
+       assert(p.second.value == -42);
+    }
+    {
+       using P = std::pair<C, C>;
+       using T = std::array<C, 2>;
+       T t = {42, -42};
+       P p{101, 101};
+       C::reset();
+       p = std::move(t);
+       assert(C::constructed == 0);
+       assert(C::assigned == 2);
+       assert(C::copy_assigned == 0);
+       assert(C::move_assigned == 2);
+       assert(p.first.value == 42);
+       assert(p.second.value == -42);
+    }
+}




More information about the cfe-commits mailing list