325 lines · cpp
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-exception6//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++0316 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 34// https://llvm.org/PR4168935struct Unconstrained {36 int data;37 template <typename Arg>38 TEST_CONSTEXPR_CXX14 Unconstrained(Arg arg) : data(arg) {}39};40 41TEST_CONSTEXPR_CXX14 bool test_tuple_cat_with_unconstrained_constructor() {42 {43 auto tup_src = std::tuple<Unconstrained>(Unconstrained(5));44 auto tup = std::tuple_cat(tup_src);45 assert(std::get<0>(tup).data == 5);46 }47 {48 auto tup = std::tuple_cat(std::tuple<Unconstrained>(Unconstrained(6)));49 assert(std::get<0>(tup).data == 6);50 }51 {52 auto tup = std::tuple_cat(std::tuple<Unconstrained>(Unconstrained(7)), std::tuple<>());53 assert(std::get<0>(tup).data == 7);54 }55#if TEST_STD_VER >= 1756 {57 auto tup_src = std::tuple(Unconstrained(8));58 auto tup = std::tuple_cat(tup_src);59 ASSERT_SAME_TYPE(decltype(tup), std::tuple<Unconstrained>);60 assert(std::get<0>(tup).data == 8);61 }62 {63 auto tup = std::tuple_cat(std::tuple(Unconstrained(9)));64 ASSERT_SAME_TYPE(decltype(tup), std::tuple<Unconstrained>);65 assert(std::get<0>(tup).data == 9);66 }67 {68 auto tup = std::tuple_cat(std::tuple(Unconstrained(10)), std::tuple());69 ASSERT_SAME_TYPE(decltype(tup), std::tuple<Unconstrained>);70 assert(std::get<0>(tup).data == 10);71 }72#endif73 return true;74}75 76int main(int, char**)77{78 {79 std::tuple<> t = std::tuple_cat();80 ((void)t); // Prevent unused warning81 }82 {83 std::tuple<> t1;84 std::tuple<> t2 = std::tuple_cat(t1);85 ((void)t2); // Prevent unused warning86 }87 {88 std::tuple<> t = std::tuple_cat(std::tuple<>());89 ((void)t); // Prevent unused warning90 }91 {92 std::tuple<> t = std::tuple_cat(std::array<int, 0>());93 ((void)t); // Prevent unused warning94 }95 {96 std::tuple<int> t1(1);97 std::tuple<int> t = std::tuple_cat(t1);98 assert(std::get<0>(t) == 1);99 }100 101#if TEST_STD_VER > 11102 {103 constexpr std::tuple<> t = std::tuple_cat();104 ((void)t); // Prevent unused warning105 }106 {107 constexpr std::tuple<> t1;108 constexpr std::tuple<> t2 = std::tuple_cat(t1);109 ((void)t2); // Prevent unused warning110 }111 {112 constexpr std::tuple<> t = std::tuple_cat(std::tuple<>());113 ((void)t); // Prevent unused warning114 }115 {116 constexpr std::tuple<> t = std::tuple_cat(std::array<int, 0>());117 ((void)t); // Prevent unused warning118 }119 {120 constexpr std::tuple<int> t1(1);121 constexpr std::tuple<int> t = std::tuple_cat(t1);122 static_assert(std::get<0>(t) == 1, "");123 }124 {125 constexpr std::tuple<int> t1(1);126 constexpr std::tuple<int, int> t = std::tuple_cat(t1, t1);127 static_assert(std::get<0>(t) == 1, "");128 static_assert(std::get<1>(t) == 1, "");129 }130#endif131 {132 std::tuple<int, MoveOnly> t =133 std::tuple_cat(std::tuple<int, MoveOnly>(1, 2));134 assert(std::get<0>(t) == 1);135 assert(std::get<1>(t) == 2);136 }137 {138 std::tuple<int, int, int> t = std::tuple_cat(std::array<int, 3>());139 assert(std::get<0>(t) == 0);140 assert(std::get<1>(t) == 0);141 assert(std::get<2>(t) == 0);142 }143 {144 std::tuple<int, MoveOnly> t = std::tuple_cat(std::pair<int, MoveOnly>(2, 1));145 assert(std::get<0>(t) == 2);146 assert(std::get<1>(t) == 1);147 }148 149 {150 std::tuple<> t1;151 std::tuple<> t2;152 std::tuple<> t3 = std::tuple_cat(t1, t2);153 ((void)t3); // Prevent unused warning154 }155 {156 std::tuple<> t1;157 std::tuple<int> t2(2);158 std::tuple<int> t3 = std::tuple_cat(t1, t2);159 assert(std::get<0>(t3) == 2);160 }161 {162 std::tuple<> t1;163 std::tuple<int> t2(2);164 std::tuple<int> t3 = std::tuple_cat(t2, t1);165 assert(std::get<0>(t3) == 2);166 }167 {168 std::tuple<int*> t1;169 std::tuple<int> t2(2);170 std::tuple<int*, int> t3 = std::tuple_cat(t1, t2);171 assert(std::get<0>(t3) == nullptr);172 assert(std::get<1>(t3) == 2);173 }174 {175 std::tuple<int*> t1;176 std::tuple<int> t2(2);177 std::tuple<int, int*> t3 = std::tuple_cat(t2, t1);178 assert(std::get<0>(t3) == 2);179 assert(std::get<1>(t3) == nullptr);180 }181 {182 std::tuple<int*> t1;183 std::tuple<int, double> t2(2, 3.5);184 std::tuple<int*, int, double> t3 = std::tuple_cat(t1, t2);185 assert(std::get<0>(t3) == nullptr);186 assert(std::get<1>(t3) == 2);187 assert(std::get<2>(t3) == 3.5);188 }189 {190 std::tuple<int*> t1;191 std::tuple<int, double> t2(2, 3.5);192 std::tuple<int, double, int*> t3 = std::tuple_cat(t2, t1);193 assert(std::get<0>(t3) == 2);194 assert(std::get<1>(t3) == 3.5);195 assert(std::get<2>(t3) == nullptr);196 }197 {198 std::tuple<int*, MoveOnly> t1(nullptr, 1);199 std::tuple<int, double> t2(2, 3.5);200 std::tuple<int*, MoveOnly, int, double> t3 =201 std::tuple_cat(std::move(t1), t2);202 assert(std::get<0>(t3) == nullptr);203 assert(std::get<1>(t3) == 1);204 assert(std::get<2>(t3) == 2);205 assert(std::get<3>(t3) == 3.5);206 }207 {208 std::tuple<int*, MoveOnly> t1(nullptr, 1);209 std::tuple<int, double> t2(2, 3.5);210 std::tuple<int, double, int*, MoveOnly> t3 =211 std::tuple_cat(t2, std::move(t1));212 assert(std::get<0>(t3) == 2);213 assert(std::get<1>(t3) == 3.5);214 assert(std::get<2>(t3) == nullptr);215 assert(std::get<3>(t3) == 1);216 }217 {218 std::tuple<MoveOnly, MoveOnly> t1(1, 2);219 std::tuple<int*, MoveOnly> t2(nullptr, 4);220 std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =221 std::tuple_cat(std::move(t1), std::move(t2));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 }227 228 {229 std::tuple<MoveOnly, MoveOnly> t1(1, 2);230 std::tuple<int*, MoveOnly> t2(nullptr, 4);231 std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =232 std::tuple_cat(std::tuple<>(),233 std::move(t1),234 std::move(t2));235 assert(std::get<0>(t3) == 1);236 assert(std::get<1>(t3) == 2);237 assert(std::get<2>(t3) == nullptr);238 assert(std::get<3>(t3) == 4);239 }240 {241 std::tuple<MoveOnly, MoveOnly> t1(1, 2);242 std::tuple<int*, MoveOnly> t2(nullptr, 4);243 std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =244 std::tuple_cat(std::move(t1),245 std::tuple<>(),246 std::move(t2));247 assert(std::get<0>(t3) == 1);248 assert(std::get<1>(t3) == 2);249 assert(std::get<2>(t3) == nullptr);250 assert(std::get<3>(t3) == 4);251 }252 {253 std::tuple<MoveOnly, MoveOnly> t1(1, 2);254 std::tuple<int*, MoveOnly> t2(nullptr, 4);255 std::tuple<MoveOnly, MoveOnly, int*, MoveOnly> t3 =256 std::tuple_cat(std::move(t1),257 std::move(t2),258 std::tuple<>());259 assert(std::get<0>(t3) == 1);260 assert(std::get<1>(t3) == 2);261 assert(std::get<2>(t3) == nullptr);262 assert(std::get<3>(t3) == 4);263 }264 {265 std::tuple<MoveOnly, MoveOnly> t1(1, 2);266 std::tuple<int*, MoveOnly> t2(nullptr, 4);267 std::tuple<MoveOnly, MoveOnly, int*, MoveOnly, int> t3 =268 std::tuple_cat(std::move(t1),269 std::move(t2),270 std::tuple<int>(5));271 assert(std::get<0>(t3) == 1);272 assert(std::get<1>(t3) == 2);273 assert(std::get<2>(t3) == nullptr);274 assert(std::get<3>(t3) == 4);275 assert(std::get<4>(t3) == 5);276 }277 {278 // See bug #19616.279 auto t1 = std::tuple_cat(280 std::make_tuple(std::make_tuple(1)),281 std::make_tuple()282 );283 assert(t1 == std::make_tuple(std::make_tuple(1)));284 285 auto t2 = std::tuple_cat(286 std::make_tuple(std::make_tuple(1)),287 std::make_tuple(std::make_tuple(2))288 );289 assert(t2 == std::make_tuple(std::make_tuple(1), std::make_tuple(2)));290 }291 {292 int x = 101;293 std::tuple<int, const int, int&, const int&, int&&> t(42, 101, x, x, std::move(x));294 const auto& ct = t;295 std::tuple<int, const int, int&, const int&> t2(42, 101, x, x);296 const auto& ct2 = t2;297 298 auto r = std::tuple_cat(std::move(t), std::move(ct), t2, ct2);299 300 ASSERT_SAME_TYPE(decltype(r), std::tuple<301 int, const int, int&, const int&, int&&,302 int, const int, int&, const int&, int&&,303 int, const int, int&, const int&,304 int, const int, int&, const int&>);305 ((void)r);306 }307 {308 std::tuple<NS::Namespaced> t1(NS::Namespaced{1});309 std::tuple<NS::Namespaced> t = std::tuple_cat(t1);310 std::tuple<NS::Namespaced, NS::Namespaced> t2 =311 std::tuple_cat(t1, t1);312 assert(std::get<0>(t).i == 1);313 assert(std::get<0>(t2).i == 1);314 }315 // See https://llvm.org/PR41689316 {317 test_tuple_cat_with_unconstrained_constructor();318#if TEST_STD_VER >= 14319 static_assert(test_tuple_cat_with_unconstrained_constructor(), "");320#endif321 }322 323 return 0;324}325