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 // Triggers a Clang assertion: llvm.org/PR45879 10 // UNSUPPORTED: clang-14, clang-15 11 12 // <tuple> 13 14 // template <class... Types> class tuple; 15 16 // template <class... UTypes> 17 // tuple& operator=(const tuple<UTypes...>& u); 18 19 // UNSUPPORTED: c++03 20 21 #include <tuple> 22 #include <string> 23 #include <cassert> 24 25 #include "test_macros.h" 26 27 struct B { 28 int id_; 29 30 constexpr explicit B(int i = 0) : id_(i) {} 31 }; 32 33 struct D : B { 34 constexpr explicit D(int i = 0) : B(i) {} 35 }; 36 37 struct NonAssignable { 38 NonAssignable& operator=(NonAssignable const&) = delete; 39 NonAssignable& operator=(NonAssignable&&) = delete; 40 }; 41 42 struct NothrowCopyAssignable { 43 NothrowCopyAssignable(NothrowCopyAssignable const&) = delete; 44 NothrowCopyAssignable& operator=(NothrowCopyAssignable const&) noexcept { return *this; } 45 }; 46 47 struct PotentiallyThrowingCopyAssignable { 48 PotentiallyThrowingCopyAssignable(PotentiallyThrowingCopyAssignable const&) = delete; 49 PotentiallyThrowingCopyAssignable& operator=(PotentiallyThrowingCopyAssignable const&) { return *this; } 50 }; 51 52 TEST_CONSTEXPR_CXX20 53 bool test() 54 { 55 { 56 typedef std::tuple<long> T0; 57 typedef std::tuple<long long> T1; 58 T0 t0(2); 59 T1 t1; 60 t1 = 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 = 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 = 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 = 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 // Test that tuple evaluates correctly applies an lvalue reference 96 // before evaluating is_assignable (i.e. 'is_assignable<int&, int&>') 97 // instead of evaluating 'is_assignable<int&&, int&>' which is false. 98 int x = 42; 99 int y = 43; 100 std::tuple<int&&> t(std::move(x)); 101 std::tuple<int&> t2(y); 102 t = t2; 103 assert(std::get<0>(t) == 43); 104 assert(&std::get<0>(t) == &x); 105 } 106 return true; 107 } 108 109 int main(int, char**) 110 { 111 test(); 112 #if TEST_STD_VER >= 20 113 static_assert(test()); 114 #endif 115 116 { 117 using T = std::tuple<int, NonAssignable>; 118 using U = std::tuple<NonAssignable, int>; 119 static_assert(!std::is_assignable<T&, U const&>::value, ""); 120 static_assert(!std::is_assignable<U&, T const&>::value, ""); 121 } 122 { 123 typedef std::tuple<NothrowCopyAssignable, long> T0; 124 typedef std::tuple<NothrowCopyAssignable, int> T1; 125 static_assert(std::is_nothrow_assignable<T0&, T1 const&>::value, ""); 126 } 127 { 128 typedef std::tuple<PotentiallyThrowingCopyAssignable, long> T0; 129 typedef std::tuple<PotentiallyThrowingCopyAssignable, int> T1; 130 static_assert(std::is_assignable<T0&, T1 const&>::value, ""); 131 static_assert(!std::is_nothrow_assignable<T0&, T1 const&>::value, ""); 132 } 133 134 return 0; 135 } 136