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... Tuples> tuple<CTypes...> tuple_cat(Tuples&&... tpls);
14 
15 // UNSUPPORTED: c++03
16 
17 #include <tuple>
18 #include <utility>
19 #include <array>
20 #include <string>
21 #include <cassert>
22 
23 #include "test_macros.h"
24 #include "MoveOnly.h"
25 
26 namespace NS {
27 struct Namespaced {
28   int i;
29 };
30 template<typename ...Ts>
31 void forward_as_tuple(Ts...) = delete;
32 }
33 
main(int,char **)34 int main(int, char**)
35 {
36     {
37         std::tuple<> t = std::tuple_cat();
38         ((void)t); // Prevent unused warning
39     }
40     {
41         std::tuple<> t1;
42         std::tuple<> t2 = std::tuple_cat(t1);
43         ((void)t2); // Prevent unused warning
44     }
45     {
46         std::tuple<> t = std::tuple_cat(std::tuple<>());
47         ((void)t); // Prevent unused warning
48     }
49     {
50         std::tuple<> t = std::tuple_cat(std::array<int, 0>());
51         ((void)t); // Prevent unused warning
52     }
53     {
54         std::tuple<int> t1(1);
55         std::tuple<int> t = std::tuple_cat(t1);
56         assert(std::get<0>(t) == 1);
57     }
58 
59 #if TEST_STD_VER > 11
60     {
61         constexpr std::tuple<> t = std::tuple_cat();
62         ((void)t); // Prevent unused warning
63     }
64     {
65         constexpr std::tuple<> t1;
66         constexpr std::tuple<> t2 = std::tuple_cat(t1);
67         ((void)t2); // Prevent unused warning
68     }
69     {
70         constexpr std::tuple<> t = std::tuple_cat(std::tuple<>());
71         ((void)t); // Prevent unused warning
72     }
73     {
74         constexpr std::tuple<> t = std::tuple_cat(std::array<int, 0>());
75         ((void)t); // Prevent unused warning
76     }
77     {
78         constexpr std::tuple<int> t1(1);
79         constexpr std::tuple<int> t = std::tuple_cat(t1);
80         static_assert(std::get<0>(t) == 1, "");
81     }
82     {
83         constexpr std::tuple<int> t1(1);
84         constexpr std::tuple<int, int> t = std::tuple_cat(t1, t1);
85         static_assert(std::get<0>(t) == 1, "");
86         static_assert(std::get<1>(t) == 1, "");
87     }
88 #endif
89     {
90         std::tuple<int, MoveOnly> t =
91                                 std::tuple_cat(std::tuple<int, MoveOnly>(1, 2));
92         assert(std::get<0>(t) == 1);
93         assert(std::get<1>(t) == 2);
94     }
95     {
96         std::tuple<int, int, int> t = std::tuple_cat(std::array<int, 3>());
97         assert(std::get<0>(t) == 0);
98         assert(std::get<1>(t) == 0);
99         assert(std::get<2>(t) == 0);
100     }
101     {
102         std::tuple<int, MoveOnly> t = std::tuple_cat(std::pair<int, MoveOnly>(2, 1));
103         assert(std::get<0>(t) == 2);
104         assert(std::get<1>(t) == 1);
105     }
106 
107     {
108         std::tuple<> t1;
109         std::tuple<> t2;
110         std::tuple<> t3 = std::tuple_cat(t1, t2);
111         ((void)t3); // Prevent unused warning
112     }
113     {
114         std::tuple<> t1;
115         std::tuple<int> t2(2);
116         std::tuple<int> t3 = std::tuple_cat(t1, t2);
117         assert(std::get<0>(t3) == 2);
118     }
119     {
120         std::tuple<> t1;
121         std::tuple<int> t2(2);
122         std::tuple<int> t3 = std::tuple_cat(t2, t1);
123         assert(std::get<0>(t3) == 2);
124     }
125     {
126         std::tuple<int*> t1;
127         std::tuple<int> t2(2);
128         std::tuple<int*, int> t3 = std::tuple_cat(t1, t2);
129         assert(std::get<0>(t3) == nullptr);
130         assert(std::get<1>(t3) == 2);
131     }
132     {
133         std::tuple<int*> t1;
134         std::tuple<int> t2(2);
135         std::tuple<int, int*> t3 = std::tuple_cat(t2, t1);
136         assert(std::get<0>(t3) == 2);
137         assert(std::get<1>(t3) == nullptr);
138     }
139     {
140         std::tuple<int*> t1;
141         std::tuple<int, double> t2(2, 3.5);
142         std::tuple<int*, int, double> t3 = std::tuple_cat(t1, t2);
143         assert(std::get<0>(t3) == nullptr);
144         assert(std::get<1>(t3) == 2);
145         assert(std::get<2>(t3) == 3.5);
146     }
147     {
148         std::tuple<int*> t1;
149         std::tuple<int, double> t2(2, 3.5);
150         std::tuple<int, double, int*> t3 = std::tuple_cat(t2, t1);
151         assert(std::get<0>(t3) == 2);
152         assert(std::get<1>(t3) == 3.5);
153         assert(std::get<2>(t3) == nullptr);
154     }
155     {
156         std::tuple<int*, MoveOnly> t1(nullptr, 1);
157         std::tuple<int, double> t2(2, 3.5);
158         std::tuple<int*, MoveOnly, int, double> t3 =
159                                               std::tuple_cat(std::move(t1), t2);
160         assert(std::get<0>(t3) == nullptr);
161         assert(std::get<1>(t3) == 1);
162         assert(std::get<2>(t3) == 2);
163         assert(std::get<3>(t3) == 3.5);
164     }
165     {
166         std::tuple<int*, MoveOnly> t1(nullptr, 1);
167         std::tuple<int, double> t2(2, 3.5);
168         std::tuple<int, double, int*, MoveOnly> t3 =
169                                               std::tuple_cat(t2, std::move(t1));
170         assert(std::get<0>(t3) == 2);
171         assert(std::get<1>(t3) == 3.5);
172         assert(std::get<2>(t3) == nullptr);
173         assert(std::get<3>(t3) == 1);
174     }
175     {
176         std::tuple<MoveOnly, MoveOnly> t1(1, 2);
177         std::tuple<int*, MoveOnly> t2(nullptr, 4);
178         std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =
179                                    std::tuple_cat(std::move(t1), std::move(t2));
180         assert(std::get<0>(t3) == 1);
181         assert(std::get<1>(t3) == 2);
182         assert(std::get<2>(t3) == nullptr);
183         assert(std::get<3>(t3) == 4);
184     }
185 
186     {
187         std::tuple<MoveOnly, MoveOnly> t1(1, 2);
188         std::tuple<int*, MoveOnly> t2(nullptr, 4);
189         std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =
190                                    std::tuple_cat(std::tuple<>(),
191                                                   std::move(t1),
192                                                   std::move(t2));
193         assert(std::get<0>(t3) == 1);
194         assert(std::get<1>(t3) == 2);
195         assert(std::get<2>(t3) == nullptr);
196         assert(std::get<3>(t3) == 4);
197     }
198     {
199         std::tuple<MoveOnly, MoveOnly> t1(1, 2);
200         std::tuple<int*, MoveOnly> t2(nullptr, 4);
201         std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =
202                                    std::tuple_cat(std::move(t1),
203                                                   std::tuple<>(),
204                                                   std::move(t2));
205         assert(std::get<0>(t3) == 1);
206         assert(std::get<1>(t3) == 2);
207         assert(std::get<2>(t3) == nullptr);
208         assert(std::get<3>(t3) == 4);
209     }
210     {
211         std::tuple<MoveOnly, MoveOnly> t1(1, 2);
212         std::tuple<int*, MoveOnly> t2(nullptr, 4);
213         std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =
214                                    std::tuple_cat(std::move(t1),
215                                                   std::move(t2),
216                                                   std::tuple<>());
217         assert(std::get<0>(t3) == 1);
218         assert(std::get<1>(t3) == 2);
219         assert(std::get<2>(t3) == nullptr);
220         assert(std::get<3>(t3) == 4);
221     }
222     {
223         std::tuple<MoveOnly, MoveOnly> t1(1, 2);
224         std::tuple<int*, MoveOnly> t2(nullptr, 4);
225         std::tuple<MoveOnly, MoveOnly, int*, MoveOnly, int> t3 =
226                                    std::tuple_cat(std::move(t1),
227                                                   std::move(t2),
228                                                   std::tuple<int>(5));
229         assert(std::get<0>(t3) == 1);
230         assert(std::get<1>(t3) == 2);
231         assert(std::get<2>(t3) == nullptr);
232         assert(std::get<3>(t3) == 4);
233         assert(std::get<4>(t3) == 5);
234     }
235     {
236         // See bug #19616.
237         auto t1 = std::tuple_cat(
238             std::make_tuple(std::make_tuple(1)),
239             std::make_tuple()
240         );
241         assert(t1 == std::make_tuple(std::make_tuple(1)));
242 
243         auto t2 = std::tuple_cat(
244             std::make_tuple(std::make_tuple(1)),
245             std::make_tuple(std::make_tuple(2))
246         );
247         assert(t2 == std::make_tuple(std::make_tuple(1), std::make_tuple(2)));
248     }
249     {
250         int x = 101;
251         std::tuple<int, const int, int&, const int&, int&&> t(42, 101, x, x, std::move(x));
252         const auto& ct = t;
253         std::tuple<int, const int, int&, const int&> t2(42, 101, x, x);
254         const auto& ct2 = t2;
255 
256         auto r = std::tuple_cat(std::move(t), std::move(ct), t2, ct2);
257 
258         ASSERT_SAME_TYPE(decltype(r), std::tuple<
259             int, const int, int&, const int&, int&&,
260             int, const int, int&, const int&, int&&,
261             int, const int, int&, const int&,
262             int, const int, int&, const int&>);
263         ((void)r);
264     }
265     {
266         std::tuple<NS::Namespaced> t1(NS::Namespaced{1});
267         std::tuple<NS::Namespaced> t = std::tuple_cat(t1);
268         std::tuple<NS::Namespaced, NS::Namespaced> t2 =
269             std::tuple_cat(t1, t1);
270         assert(std::get<0>(t).i == 1);
271         assert(std::get<0>(t2).i == 1);
272     }
273   return 0;
274 }
275