1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // <tuple> 11 12 // template <class... Types> class tuple; 13 14 // tuple& operator=(tuple&& u); 15 16 // UNSUPPORTED: c++98, c++03 17 18 #include <tuple> 19 #include <utility> 20 #include <cassert> 21 22 #include "MoveOnly.h" 23 24 struct NonAssignable { 25 NonAssignable& operator=(NonAssignable const&) = delete; 26 NonAssignable& operator=(NonAssignable&&) = delete; 27 }; 28 struct CopyAssignable { 29 CopyAssignable& operator=(CopyAssignable const&) = default; 30 CopyAssignable& operator=(CopyAssignable&&) = delete; 31 }; 32 static_assert(std::is_copy_assignable<CopyAssignable>::value, ""); 33 struct MoveAssignable { 34 MoveAssignable& operator=(MoveAssignable const&) = delete; 35 MoveAssignable& operator=(MoveAssignable&&) = default; 36 }; 37 38 39 struct CountAssign { 40 static int copied; 41 static int moved; 42 static void reset() { copied = moved = 0; } 43 CountAssign() = default; 44 CountAssign& operator=(CountAssign const&) { ++copied; return *this; } 45 CountAssign& operator=(CountAssign&&) { ++moved; return *this; } 46 }; 47 int CountAssign::copied = 0; 48 int CountAssign::moved = 0; 49 50 51 int main() 52 { 53 { 54 typedef std::tuple<> T; 55 T t0; 56 T t; 57 t = std::move(t0); 58 } 59 { 60 typedef std::tuple<MoveOnly> T; 61 T t0(MoveOnly(0)); 62 T t; 63 t = std::move(t0); 64 assert(std::get<0>(t) == 0); 65 } 66 { 67 typedef std::tuple<MoveOnly, MoveOnly> T; 68 T t0(MoveOnly(0), MoveOnly(1)); 69 T t; 70 t = std::move(t0); 71 assert(std::get<0>(t) == 0); 72 assert(std::get<1>(t) == 1); 73 } 74 { 75 typedef std::tuple<MoveOnly, MoveOnly, MoveOnly> T; 76 T t0(MoveOnly(0), MoveOnly(1), MoveOnly(2)); 77 T t; 78 t = std::move(t0); 79 assert(std::get<0>(t) == 0); 80 assert(std::get<1>(t) == 1); 81 assert(std::get<2>(t) == 2); 82 } 83 { 84 // test reference assignment. 85 using T = std::tuple<int&, int&&>; 86 int x = 42; 87 int y = 100; 88 int x2 = -1; 89 int y2 = 500; 90 T t(x, std::move(y)); 91 T t2(x2, std::move(y2)); 92 t = std::move(t2); 93 assert(std::get<0>(t) == x2); 94 assert(&std::get<0>(t) == &x); 95 assert(std::get<1>(t) == y2); 96 assert(&std::get<1>(t) == &y); 97 } 98 { 99 // test that the implicitly generated move assignment operator 100 // is properly deleted 101 using T = std::tuple<std::unique_ptr<int>>; 102 static_assert(std::is_move_assignable<T>::value, ""); 103 static_assert(!std::is_copy_assignable<T>::value, ""); 104 105 } 106 { 107 using T = std::tuple<int, NonAssignable>; 108 static_assert(!std::is_move_assignable<T>::value, ""); 109 } 110 { 111 using T = std::tuple<int, MoveAssignable>; 112 static_assert(std::is_move_assignable<T>::value, ""); 113 } 114 { 115 // The move should decay to a copy. 116 CountAssign::reset(); 117 using T = std::tuple<CountAssign, CopyAssignable>; 118 static_assert(std::is_move_assignable<T>::value, ""); 119 T t1; 120 T t2; 121 t1 = std::move(t2); 122 assert(CountAssign::copied == 1); 123 assert(CountAssign::moved == 0); 124 } 125 } 126