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 int main(int, char**) 54 { 55 { 56 typedef std::tuple<long> T0; 57 typedef std::tuple<long long> T1; 58 T0 t0(2); 59 T1 t1; 60 t1 = std::move(t0); 61 assert(std::get<0>(t1) == 2); 62 } 63 { 64 typedef std::tuple<long, char> T0; 65 typedef std::tuple<long long, int> T1; 66 T0 t0(2, 'a'); 67 T1 t1; 68 t1 = std::move(t0); 69 assert(std::get<0>(t1) == 2); 70 assert(std::get<1>(t1) == int('a')); 71 } 72 { 73 typedef std::tuple<long, char, D> T0; 74 typedef std::tuple<long long, int, B> T1; 75 T0 t0(2, 'a', D(3)); 76 T1 t1; 77 t1 = std::move(t0); 78 assert(std::get<0>(t1) == 2); 79 assert(std::get<1>(t1) == int('a')); 80 assert(std::get<2>(t1).id_ == 3); 81 } 82 { 83 D d(3); 84 D d2(2); 85 typedef std::tuple<long, char, D&> T0; 86 typedef std::tuple<long long, int, B&> T1; 87 T0 t0(2, 'a', d2); 88 T1 t1(1, 'b', d); 89 t1 = std::move(t0); 90 assert(std::get<0>(t1) == 2); 91 assert(std::get<1>(t1) == int('a')); 92 assert(std::get<2>(t1).id_ == 2); 93 } 94 { 95 typedef std::tuple<long, char, std::unique_ptr<D>> T0; 96 typedef std::tuple<long long, int, std::unique_ptr<B>> T1; 97 T0 t0(2, 'a', std::unique_ptr<D>(new D(3))); 98 T1 t1; 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_ == 3); 103 } 104 { 105 // Test that tuple evaluates correctly applies an lvalue reference 106 // before evaluating is_assignable (i.e. 'is_assignable<int&, int&&>') 107 // instead of evaluating 'is_assignable<int&&, int&&>' which is false. 108 int x = 42; 109 int y = 43; 110 std::tuple<int&&, E> t(std::move(x), E{}); 111 std::tuple<int&&, int> t2(std::move(y), 44); 112 t = std::move(t2); 113 assert(std::get<0>(t) == 43); 114 assert(&std::get<0>(t) == &x); 115 } 116 { 117 using T = std::tuple<int, NonAssignable>; 118 using U = std::tuple<NonAssignable, int>; 119 static_assert(!std::is_assignable<T, U&&>::value, ""); 120 static_assert(!std::is_assignable<U, T&&>::value, ""); 121 } 122 123 return 0; 124 } 125