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 <memory> 19 #include <tuple> 20 #include <utility> 21 #include <cassert> 22 23 #include "MoveOnly.h" 24 25 struct NonAssignable { 26 NonAssignable& operator=(NonAssignable const&) = delete; 27 NonAssignable& operator=(NonAssignable&&) = delete; 28 }; 29 struct CopyAssignable { 30 CopyAssignable& operator=(CopyAssignable const&) = default; 31 CopyAssignable& operator=(CopyAssignable&&) = delete; 32 }; 33 static_assert(std::is_copy_assignable<CopyAssignable>::value, ""); 34 struct MoveAssignable { 35 MoveAssignable& operator=(MoveAssignable const&) = delete; 36 MoveAssignable& operator=(MoveAssignable&&) = default; 37 }; 38 39 40 struct CountAssign { 41 static int copied; 42 static int moved; 43 static void reset() { copied = moved = 0; } 44 CountAssign() = default; 45 CountAssign& operator=(CountAssign const&) { ++copied; return *this; } 46 CountAssign& operator=(CountAssign&&) { ++moved; return *this; } 47 }; 48 int CountAssign::copied = 0; 49 int CountAssign::moved = 0; 50 51 52 int main() 53 { 54 { 55 typedef std::tuple<> T; 56 T t0; 57 T t; 58 t = std::move(t0); 59 } 60 { 61 typedef std::tuple<MoveOnly> T; 62 T t0(MoveOnly(0)); 63 T t; 64 t = std::move(t0); 65 assert(std::get<0>(t) == 0); 66 } 67 { 68 typedef std::tuple<MoveOnly, MoveOnly> T; 69 T t0(MoveOnly(0), MoveOnly(1)); 70 T t; 71 t = std::move(t0); 72 assert(std::get<0>(t) == 0); 73 assert(std::get<1>(t) == 1); 74 } 75 { 76 typedef std::tuple<MoveOnly, MoveOnly, MoveOnly> T; 77 T t0(MoveOnly(0), MoveOnly(1), MoveOnly(2)); 78 T t; 79 t = std::move(t0); 80 assert(std::get<0>(t) == 0); 81 assert(std::get<1>(t) == 1); 82 assert(std::get<2>(t) == 2); 83 } 84 { 85 // test reference assignment. 86 using T = std::tuple<int&, int&&>; 87 int x = 42; 88 int y = 100; 89 int x2 = -1; 90 int y2 = 500; 91 T t(x, std::move(y)); 92 T t2(x2, std::move(y2)); 93 t = std::move(t2); 94 assert(std::get<0>(t) == x2); 95 assert(&std::get<0>(t) == &x); 96 assert(std::get<1>(t) == y2); 97 assert(&std::get<1>(t) == &y); 98 } 99 { 100 // test that the implicitly generated move assignment operator 101 // is properly deleted 102 using T = std::tuple<std::unique_ptr<int>>; 103 static_assert(std::is_move_assignable<T>::value, ""); 104 static_assert(!std::is_copy_assignable<T>::value, ""); 105 106 } 107 { 108 using T = std::tuple<int, NonAssignable>; 109 static_assert(!std::is_move_assignable<T>::value, ""); 110 } 111 { 112 using T = std::tuple<int, MoveAssignable>; 113 static_assert(std::is_move_assignable<T>::value, ""); 114 } 115 { 116 // The move should decay to a copy. 117 CountAssign::reset(); 118 using T = std::tuple<CountAssign, CopyAssignable>; 119 static_assert(std::is_move_assignable<T>::value, ""); 120 T t1; 121 T t2; 122 t1 = std::move(t2); 123 assert(CountAssign::copied == 1); 124 assert(CountAssign::moved == 0); 125 } 126 } 127