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=(const tuple<UTypes...>& u); 15 16 // UNSUPPORTED: c++03 17 18 #include <tuple> 19 #include <string> 20 #include <cassert> 21 22 #include "test_macros.h" 23 24 struct B { 25 int id_; 26 27 constexpr explicit B(int i = 0) : id_(i) {} 28 }; 29 30 struct D : B { 31 constexpr explicit D(int i = 0) : B(i) {} 32 }; 33 34 struct NonAssignable { 35 NonAssignable& operator=(NonAssignable const&) = delete; 36 NonAssignable& operator=(NonAssignable&&) = delete; 37 }; 38 39 struct NothrowCopyAssignable { 40 NothrowCopyAssignable& operator=(NothrowCopyAssignable const&) noexcept { return *this; } 41 }; 42 43 struct PotentiallyThrowingCopyAssignable { 44 PotentiallyThrowingCopyAssignable& operator=(PotentiallyThrowingCopyAssignable const&) { return *this; } 45 }; 46 47 TEST_CONSTEXPR_CXX20 48 bool test() 49 { 50 { 51 typedef std::tuple<long> T0; 52 typedef std::tuple<long long> T1; 53 T0 t0(2); 54 T1 t1; 55 t1 = t0; 56 assert(std::get<0>(t1) == 2); 57 } 58 { 59 typedef std::tuple<long, char> T0; 60 typedef std::tuple<long long, int> T1; 61 T0 t0(2, 'a'); 62 T1 t1; 63 t1 = t0; 64 assert(std::get<0>(t1) == 2); 65 assert(std::get<1>(t1) == int('a')); 66 } 67 { 68 typedef std::tuple<long, char, D> T0; 69 typedef std::tuple<long long, int, B> T1; 70 T0 t0(2, 'a', D(3)); 71 T1 t1; 72 t1 = t0; 73 assert(std::get<0>(t1) == 2); 74 assert(std::get<1>(t1) == int('a')); 75 assert(std::get<2>(t1).id_ == 3); 76 } 77 { 78 D d(3); 79 D d2(2); 80 typedef std::tuple<long, char, D&> T0; 81 typedef std::tuple<long long, int, B&> T1; 82 T0 t0(2, 'a', d2); 83 T1 t1(1, 'b', d); 84 t1 = t0; 85 assert(std::get<0>(t1) == 2); 86 assert(std::get<1>(t1) == int('a')); 87 assert(std::get<2>(t1).id_ == 2); 88 } 89 { 90 // Test that tuple evaluates correctly applies an lvalue reference 91 // before evaluating is_assignable (i.e. 'is_assignable<int&, int&>') 92 // instead of evaluating 'is_assignable<int&&, int&>' which is false. 93 int x = 42; 94 int y = 43; 95 std::tuple<int&&> t(std::move(x)); 96 std::tuple<int&> t2(y); 97 t = t2; 98 assert(std::get<0>(t) == 43); 99 assert(&std::get<0>(t) == &x); 100 } 101 return true; 102 } 103 104 int main(int, char**) 105 { 106 test(); 107 #if TEST_STD_VER >= 20 108 static_assert(test()); 109 #endif 110 111 { 112 using T = std::tuple<int, NonAssignable>; 113 using U = std::tuple<NonAssignable, int>; 114 static_assert(!std::is_assignable<T&, U const&>::value, ""); 115 static_assert(!std::is_assignable<U&, T const&>::value, ""); 116 } 117 { 118 typedef std::tuple<NothrowCopyAssignable, long> T0; 119 typedef std::tuple<NothrowCopyAssignable, int> T1; 120 static_assert(std::is_nothrow_assignable<T0&, T1 const&>::value, ""); 121 } 122 { 123 typedef std::tuple<PotentiallyThrowingCopyAssignable, long> T0; 124 typedef std::tuple<PotentiallyThrowingCopyAssignable, int> T1; 125 static_assert(std::is_assignable<T0&, T1 const&>::value, ""); 126 static_assert(!std::is_nothrow_assignable<T0&, T1 const&>::value, ""); 127 } 128 129 return 0; 130 } 131