xref: /llvm-project/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp (revision 06e2b737aa0347b42e8bf37cb00a053eab0a9393)
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 // tuple& operator=(const tuple& u);
14 
15 // UNSUPPORTED: c++03
16 
17 #include <tuple>
18 #include <memory>
19 #include <string>
20 #include <cassert>
21 
22 #include "test_macros.h"
23 
24 struct NonAssignable {
25   NonAssignable& operator=(NonAssignable const&) = delete;
26   NonAssignable& operator=(NonAssignable&&) = delete;
27 };
28 struct CopyAssignable {
29   CopyAssignable& operator=(CopyAssignable const&) = default;
30   CopyAssignable& operator=(CopyAssignable &&) = delete;
31 };
32 static_assert(std::is_copy_assignable<CopyAssignable>::value, "");
33 struct MoveAssignable {
34   MoveAssignable& operator=(MoveAssignable const&) = delete;
35   MoveAssignable& operator=(MoveAssignable&&) = default;
36 };
37 struct NothrowCopyAssignable {
operator =NothrowCopyAssignable38   NothrowCopyAssignable& operator=(NothrowCopyAssignable const&) noexcept { return *this; }
39 };
40 struct PotentiallyThrowingCopyAssignable {
operator =PotentiallyThrowingCopyAssignable41   PotentiallyThrowingCopyAssignable& operator=(PotentiallyThrowingCopyAssignable const&) { return *this; }
42 };
43 
44 struct CopyAssignableInt {
operator =CopyAssignableInt45   CopyAssignableInt& operator=(int&) { return *this; }
46 };
47 
48 TEST_CONSTEXPR_CXX20
test()49 bool test()
50 {
51     {
52         typedef std::tuple<> T;
53         T t0;
54         T t;
55         t = t0;
56     }
57     {
58         typedef std::tuple<int> T;
59         T t0(2);
60         T t;
61         t = t0;
62         assert(std::get<0>(t) == 2);
63     }
64     {
65         typedef std::tuple<int, char> T;
66         T t0(2, 'a');
67         T t;
68         t = t0;
69         assert(std::get<0>(t) == 2);
70         assert(std::get<1>(t) == 'a');
71     }
72     {
73         // test reference assignment.
74         using T = std::tuple<int&, int&&>;
75         int x = 42;
76         int y = 100;
77         int x2 = -1;
78         int y2 = 500;
79         T t(x, std::move(y));
80         T t2(x2, std::move(y2));
81         t = t2;
82         assert(std::get<0>(t) == x2);
83         assert(&std::get<0>(t) == &x);
84         assert(std::get<1>(t) == y2);
85         assert(&std::get<1>(t) == &y);
86     }
87 
88     return true;
89 }
90 
main(int,char **)91 int main(int, char**)
92 {
93     test();
94 #if TEST_STD_VER >= 20
95     static_assert(test());
96 #endif
97 
98     {
99         // cannot be constexpr because of std::string
100         typedef std::tuple<int, char, std::string> T;
101         const T t0(2, 'a', "some text");
102         T t;
103         t = t0;
104         assert(std::get<0>(t) == 2);
105         assert(std::get<1>(t) == 'a');
106         assert(std::get<2>(t) == "some text");
107     }
108     {
109         // test that the implicitly generated copy assignment operator
110         // is properly deleted
111         using T = std::tuple<std::unique_ptr<int>>;
112         static_assert(!std::is_copy_assignable<T>::value, "");
113     }
114     {
115         using T = std::tuple<int, NonAssignable>;
116         static_assert(!std::is_copy_assignable<T>::value, "");
117     }
118     {
119         using T = std::tuple<int, CopyAssignable>;
120         static_assert(std::is_copy_assignable<T>::value, "");
121     }
122     {
123         using T = std::tuple<int, MoveAssignable>;
124         static_assert(!std::is_copy_assignable<T>::value, "");
125     }
126     {
127         using T = std::tuple<int, int, int>;
128         using P = std::pair<int, int>;
129         static_assert(!std::is_assignable<T&, P>::value, "");
130     }
131     {
132         // test const requirement
133         using T = std::tuple<CopyAssignableInt, CopyAssignableInt>;
134         using P = std::pair<int, int>;
135         static_assert(!std::is_assignable<T&, P const>::value, "");
136     }
137     {
138         using T = std::tuple<int, MoveAssignable>;
139         using P = std::pair<int, MoveAssignable>;
140         static_assert(!std::is_assignable<T&, P&>::value, "");
141     }
142     {
143         using T = std::tuple<NothrowCopyAssignable, int>;
144         static_assert(std::is_nothrow_copy_assignable<T>::value, "");
145     }
146     {
147         using T = std::tuple<PotentiallyThrowingCopyAssignable, int>;
148         static_assert(std::is_copy_assignable<T>::value, "");
149         static_assert(!std::is_nothrow_copy_assignable<T>::value, "");
150     }
151 
152     return 0;
153 }
154