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 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