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