1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // <tuple> 10 11 // template <class... Types> class tuple; 12 13 // template <class... UTypes> 14 // tuple& operator=(tuple<UTypes...>&& u); 15 16 // UNSUPPORTED: c++03 17 18 #include <tuple> 19 #include <string> 20 #include <memory> 21 #include <utility> 22 #include <cassert> 23 24 #include "test_macros.h" 25 26 struct B 27 { 28 int id_; 29 30 explicit B(int i= 0) : id_(i) {} 31 32 virtual ~B() {} 33 }; 34 35 struct D 36 : B 37 { 38 explicit D(int i) : B(i) {} 39 }; 40 41 struct E { 42 E() = default; 43 E& operator=(int) { 44 return *this; 45 } 46 }; 47 48 struct NonAssignable { 49 NonAssignable& operator=(NonAssignable const&) = delete; 50 NonAssignable& operator=(NonAssignable&&) = delete; 51 }; 52 53 struct NothrowMoveAssignable 54 { 55 NothrowMoveAssignable& operator=(NothrowMoveAssignable&&) noexcept { return *this; } 56 }; 57 58 struct PotentiallyThrowingMoveAssignable 59 { 60 PotentiallyThrowingMoveAssignable& operator=(PotentiallyThrowingMoveAssignable&&) { return *this; } 61 }; 62 63 int main(int, char**) 64 { 65 { 66 typedef std::tuple<long> T0; 67 typedef std::tuple<long long> T1; 68 T0 t0(2); 69 T1 t1; 70 t1 = std::move(t0); 71 assert(std::get<0>(t1) == 2); 72 } 73 { 74 typedef std::tuple<long, char> T0; 75 typedef std::tuple<long long, int> T1; 76 T0 t0(2, 'a'); 77 T1 t1; 78 t1 = std::move(t0); 79 assert(std::get<0>(t1) == 2); 80 assert(std::get<1>(t1) == int('a')); 81 } 82 { 83 typedef std::tuple<long, char, D> T0; 84 typedef std::tuple<long long, int, B> T1; 85 T0 t0(2, 'a', D(3)); 86 T1 t1; 87 t1 = std::move(t0); 88 assert(std::get<0>(t1) == 2); 89 assert(std::get<1>(t1) == int('a')); 90 assert(std::get<2>(t1).id_ == 3); 91 } 92 { 93 D d(3); 94 D d2(2); 95 typedef std::tuple<long, char, D&> T0; 96 typedef std::tuple<long long, int, B&> T1; 97 T0 t0(2, 'a', d2); 98 T1 t1(1, 'b', d); 99 t1 = std::move(t0); 100 assert(std::get<0>(t1) == 2); 101 assert(std::get<1>(t1) == int('a')); 102 assert(std::get<2>(t1).id_ == 2); 103 } 104 { 105 typedef std::tuple<long, char, std::unique_ptr<D>> T0; 106 typedef std::tuple<long long, int, std::unique_ptr<B>> T1; 107 T0 t0(2, 'a', std::unique_ptr<D>(new D(3))); 108 T1 t1; 109 t1 = std::move(t0); 110 assert(std::get<0>(t1) == 2); 111 assert(std::get<1>(t1) == int('a')); 112 assert(std::get<2>(t1)->id_ == 3); 113 } 114 { 115 // Test that tuple evaluates correctly applies an lvalue reference 116 // before evaluating is_assignable (i.e. 'is_assignable<int&, int&&>') 117 // instead of evaluating 'is_assignable<int&&, int&&>' which is false. 118 int x = 42; 119 int y = 43; 120 std::tuple<int&&, E> t(std::move(x), E{}); 121 std::tuple<int&&, int> t2(std::move(y), 44); 122 t = std::move(t2); 123 assert(std::get<0>(t) == 43); 124 assert(&std::get<0>(t) == &x); 125 } 126 { 127 using T = std::tuple<int, NonAssignable>; 128 using U = std::tuple<NonAssignable, int>; 129 static_assert(!std::is_assignable<T, U&&>::value, ""); 130 static_assert(!std::is_assignable<U, T&&>::value, ""); 131 } 132 { 133 typedef std::tuple<NothrowMoveAssignable, long> T0; 134 typedef std::tuple<NothrowMoveAssignable, int> T1; 135 static_assert(std::is_nothrow_assignable<T0&, T1&&>::value, ""); 136 } 137 { 138 typedef std::tuple<PotentiallyThrowingMoveAssignable, long> T0; 139 typedef std::tuple<PotentiallyThrowingMoveAssignable, int> T1; 140 static_assert(!std::is_nothrow_assignable<T0&, T1&&>::value, ""); 141 } 142 143 return 0; 144 } 145