1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// <tuple>
11
12// template <class... Types> class tuple;
13
14// template <class... Tuples> tuple<CTypes...> tuple_cat(Tuples&&... tpls);
15
16// UNSUPPORTED: c++98, c++03
17
18#include <tuple>
19#include <utility>
20#include <array>
21#include <string>
22#include <cassert>
23
24#include "test_macros.h"
25#include "MoveOnly.h"
26
27int main()
28{
29    {
30        std::tuple<> t = std::tuple_cat();
31        ((void)t); // Prevent unused warning
32    }
33    {
34        std::tuple<> t1;
35        std::tuple<> t2 = std::tuple_cat(t1);
36        ((void)t2); // Prevent unused warning
37    }
38    {
39        std::tuple<> t = std::tuple_cat(std::tuple<>());
40        ((void)t); // Prevent unused warning
41    }
42    {
43        std::tuple<> t = std::tuple_cat(std::array<int, 0>());
44        ((void)t); // Prevent unused warning
45    }
46    {
47        std::tuple<int> t1(1);
48        std::tuple<int> t = std::tuple_cat(t1);
49        assert(std::get<0>(t) == 1);
50    }
51
52#if TEST_STD_VER > 11
53    {
54        constexpr std::tuple<> t = std::tuple_cat();
55        ((void)t); // Prevent unused warning
56    }
57    {
58        constexpr std::tuple<> t1;
59        constexpr std::tuple<> t2 = std::tuple_cat(t1);
60        ((void)t2); // Prevent unused warning
61    }
62    {
63        constexpr std::tuple<> t = std::tuple_cat(std::tuple<>());
64        ((void)t); // Prevent unused warning
65    }
66    {
67        constexpr std::tuple<> t = std::tuple_cat(std::array<int, 0>());
68        ((void)t); // Prevent unused warning
69    }
70    {
71        constexpr std::tuple<int> t1(1);
72        constexpr std::tuple<int> t = std::tuple_cat(t1);
73        static_assert(std::get<0>(t) == 1, "");
74    }
75    {
76        constexpr std::tuple<int> t1(1);
77        constexpr std::tuple<int, int> t = std::tuple_cat(t1, t1);
78        static_assert(std::get<0>(t) == 1, "");
79        static_assert(std::get<1>(t) == 1, "");
80    }
81#endif
82    {
83        std::tuple<int, MoveOnly> t =
84                                std::tuple_cat(std::tuple<int, MoveOnly>(1, 2));
85        assert(std::get<0>(t) == 1);
86        assert(std::get<1>(t) == 2);
87    }
88    {
89        std::tuple<int, int, int> t = std::tuple_cat(std::array<int, 3>());
90        assert(std::get<0>(t) == 0);
91        assert(std::get<1>(t) == 0);
92        assert(std::get<2>(t) == 0);
93    }
94    {
95        std::tuple<int, MoveOnly> t = std::tuple_cat(std::pair<int, MoveOnly>(2, 1));
96        assert(std::get<0>(t) == 2);
97        assert(std::get<1>(t) == 1);
98    }
99
100    {
101        std::tuple<> t1;
102        std::tuple<> t2;
103        std::tuple<> t3 = std::tuple_cat(t1, t2);
104        ((void)t3); // Prevent unused warning
105    }
106    {
107        std::tuple<> t1;
108        std::tuple<int> t2(2);
109        std::tuple<int> t3 = std::tuple_cat(t1, t2);
110        assert(std::get<0>(t3) == 2);
111    }
112    {
113        std::tuple<> t1;
114        std::tuple<int> t2(2);
115        std::tuple<int> t3 = std::tuple_cat(t2, t1);
116        assert(std::get<0>(t3) == 2);
117    }
118    {
119        std::tuple<int*> t1;
120        std::tuple<int> t2(2);
121        std::tuple<int*, int> t3 = std::tuple_cat(t1, t2);
122        assert(std::get<0>(t3) == nullptr);
123        assert(std::get<1>(t3) == 2);
124    }
125    {
126        std::tuple<int*> t1;
127        std::tuple<int> t2(2);
128        std::tuple<int, int*> t3 = std::tuple_cat(t2, t1);
129        assert(std::get<0>(t3) == 2);
130        assert(std::get<1>(t3) == nullptr);
131    }
132    {
133        std::tuple<int*> t1;
134        std::tuple<int, double> t2(2, 3.5);
135        std::tuple<int*, int, double> t3 = std::tuple_cat(t1, t2);
136        assert(std::get<0>(t3) == nullptr);
137        assert(std::get<1>(t3) == 2);
138        assert(std::get<2>(t3) == 3.5);
139    }
140    {
141        std::tuple<int*> t1;
142        std::tuple<int, double> t2(2, 3.5);
143        std::tuple<int, double, int*> t3 = std::tuple_cat(t2, t1);
144        assert(std::get<0>(t3) == 2);
145        assert(std::get<1>(t3) == 3.5);
146        assert(std::get<2>(t3) == nullptr);
147    }
148    {
149        std::tuple<int*, MoveOnly> t1(nullptr, 1);
150        std::tuple<int, double> t2(2, 3.5);
151        std::tuple<int*, MoveOnly, int, double> t3 =
152                                              std::tuple_cat(std::move(t1), t2);
153        assert(std::get<0>(t3) == nullptr);
154        assert(std::get<1>(t3) == 1);
155        assert(std::get<2>(t3) == 2);
156        assert(std::get<3>(t3) == 3.5);
157    }
158    {
159        std::tuple<int*, MoveOnly> t1(nullptr, 1);
160        std::tuple<int, double> t2(2, 3.5);
161        std::tuple<int, double, int*, MoveOnly> t3 =
162                                              std::tuple_cat(t2, std::move(t1));
163        assert(std::get<0>(t3) == 2);
164        assert(std::get<1>(t3) == 3.5);
165        assert(std::get<2>(t3) == nullptr);
166        assert(std::get<3>(t3) == 1);
167    }
168    {
169        std::tuple<MoveOnly, MoveOnly> t1(1, 2);
170        std::tuple<int*, MoveOnly> t2(nullptr, 4);
171        std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =
172                                   std::tuple_cat(std::move(t1), std::move(t2));
173        assert(std::get<0>(t3) == 1);
174        assert(std::get<1>(t3) == 2);
175        assert(std::get<2>(t3) == nullptr);
176        assert(std::get<3>(t3) == 4);
177    }
178
179    {
180        std::tuple<MoveOnly, MoveOnly> t1(1, 2);
181        std::tuple<int*, MoveOnly> t2(nullptr, 4);
182        std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =
183                                   std::tuple_cat(std::tuple<>(),
184                                                  std::move(t1),
185                                                  std::move(t2));
186        assert(std::get<0>(t3) == 1);
187        assert(std::get<1>(t3) == 2);
188        assert(std::get<2>(t3) == nullptr);
189        assert(std::get<3>(t3) == 4);
190    }
191    {
192        std::tuple<MoveOnly, MoveOnly> t1(1, 2);
193        std::tuple<int*, MoveOnly> t2(nullptr, 4);
194        std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =
195                                   std::tuple_cat(std::move(t1),
196                                                  std::tuple<>(),
197                                                  std::move(t2));
198        assert(std::get<0>(t3) == 1);
199        assert(std::get<1>(t3) == 2);
200        assert(std::get<2>(t3) == nullptr);
201        assert(std::get<3>(t3) == 4);
202    }
203    {
204        std::tuple<MoveOnly, MoveOnly> t1(1, 2);
205        std::tuple<int*, MoveOnly> t2(nullptr, 4);
206        std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =
207                                   std::tuple_cat(std::move(t1),
208                                                  std::move(t2),
209                                                  std::tuple<>());
210        assert(std::get<0>(t3) == 1);
211        assert(std::get<1>(t3) == 2);
212        assert(std::get<2>(t3) == nullptr);
213        assert(std::get<3>(t3) == 4);
214    }
215    {
216        std::tuple<MoveOnly, MoveOnly> t1(1, 2);
217        std::tuple<int*, MoveOnly> t2(nullptr, 4);
218        std::tuple<MoveOnly, MoveOnly, int*, MoveOnly, int> t3 =
219                                   std::tuple_cat(std::move(t1),
220                                                  std::move(t2),
221                                                  std::tuple<int>(5));
222        assert(std::get<0>(t3) == 1);
223        assert(std::get<1>(t3) == 2);
224        assert(std::get<2>(t3) == nullptr);
225        assert(std::get<3>(t3) == 4);
226        assert(std::get<4>(t3) == 5);
227    }
228    {
229        // See bug #19616.
230        auto t1 = std::tuple_cat(
231            std::make_tuple(std::make_tuple(1)),
232            std::make_tuple()
233        );
234        assert(t1 == std::make_tuple(std::make_tuple(1)));
235
236        auto t2 = std::tuple_cat(
237            std::make_tuple(std::make_tuple(1)),
238            std::make_tuple(std::make_tuple(2))
239        );
240        assert(t2 == std::make_tuple(std::make_tuple(1), std::make_tuple(2)));
241    }
242}
243