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
26namespace NS {
27struct Namespaced {
28 int i;
29};
30template<typename ...Ts>
31void forward_as_tuple(Ts...) = delete;
32}
33
34int 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(tpls&: t1);
43 ((void)t2); // Prevent unused warning
44 }
45 {
46 std::tuple<> t = std::tuple_cat(tpls: std::tuple<>());
47 ((void)t); // Prevent unused warning
48 }
49 {
50 std::tuple<> t = std::tuple_cat(tpls: 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(tpls&: 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(tpls: 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(tpls&: t1, tpls&: 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(tpls&: t1, tpls&: 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(tpls&: t2, tpls&: 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(tpls&: t1, tpls&: 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(tpls&: t2, tpls&: 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(tpls&: t1, tpls&: 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(tpls&: t2, tpls&: 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 tpls: std::make_tuple(args: std::make_tuple(args: 1)),
239 tpls: std::make_tuple()
240 );
241 assert(t1 == std::make_tuple(std::make_tuple(1)));
242
243 auto t2 = std::tuple_cat(
244 tpls: std::make_tuple(args: std::make_tuple(args: 1)),
245 tpls: std::make_tuple(args: std::make_tuple(args: 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(tpls: std::move(t), tpls: std::move(ct), tpls&: t2, tpls: 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{.i: 1});
267 std::tuple<NS::Namespaced> t = std::tuple_cat(tpls&: t1);
268 std::tuple<NS::Namespaced, NS::Namespaced> t2 =
269 std::tuple_cat(tpls&: t1, tpls&: t1);
270 assert(std::get<0>(t).i == 1);
271 assert(std::get<0>(t2).i == 1);
272 }
273 return 0;
274}
275

source code of libcxx/test/std/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp