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