262 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -std=c++26 %s -verify2// RUN: %clang_cc1 -fsyntax-only -std=c++26 %s -verify -fexperimental-new-constant-interpreter3 4template <typename T>5struct type_ { };6 7template <typename ...T>8constexpr auto sum(T... t) { return (t + ...); }9 10struct my_struct {11 int a;12 int b;13 int c;14 int d;15};16 17struct fake_tuple {18 int arr[4] = {1, 2, 3, 6};19 20 template <unsigned i>21 constexpr int& get() {22 return arr[i];23 }24};25 26namespace std {27 template <typename T>28 struct tuple_size;29 template <unsigned i, typename T>30 struct tuple_element;31 32 template <>33 struct tuple_size<fake_tuple> {34 static constexpr unsigned value = 4;35 };36 37 template <unsigned i>38 struct tuple_element<i, fake_tuple> {39 using type = int;40 };41}42 43 44template <typename T>45void decompose_tuple() {46 auto tup = T{{1, 2, 3, 6}};47 auto&& [x, ...rest, y] = tup;48 49 ((void)type_<int>(type_<decltype(rest)>{}), ...);50 51 T arrtup[2] = {T{{1, 2, 3, 6}},52 T{{7, 9, 10, 11}}};53 int sum = 0;54 for (auto [...xs] : arrtup) {55 sum += (xs + ...);56 }57}58 59template <typename T>60void decompose_struct() {61 T obj{1, 2, 3, 6};62 auto [x, ...rest, y] = obj;63 static_assert(sizeof...(rest) == 2);64 65 auto [...empty] = type_<int>{};66 static_assert(sizeof...(empty) == 0);67}68 69template <typename T>70void decompose_array() {71 int arr[4] = {1, 2, 3, 6};72 auto [x, ...rest, y] = arr;73 74 static_assert(sizeof...(rest) == 2);75 int size = sizeof...(rest);76 T arr2[sizeof...(rest)] = {rest...};77 auto [...pack] = arr2;78 79 // Array of size 1.80 int arr1[1] = {1};81 auto [a, ...b] = arr1;82 static_assert(sizeof...(b) == 0);83 auto [...c] = arr1;84 static_assert(sizeof...(c) == 1);85 auto [a1, ...b1, c1] = arr1; // expected-error{{binds to 1 element, but 3 names were provided}}86}87 88// Test case by Younan Zhang.89template <unsigned... P>90struct S {91 template <unsigned... Q>92 struct N {93 void foo() {94 int arr[] = {P..., Q...};95 auto [x, y, ...rest] = arr;96 [&]() {97 static_assert(sizeof...(rest) + 2 == sizeof...(P) + sizeof...(Q));98 }();99 }100 };101};102 103struct bit_fields {104 int a : 4 {1};105 int b : 4 {2};106 int c : 4 {3};107 int d : 4 {4};108};109 110template <typename T>111void decompose_bit_field() {112 auto [...x] = T{};113 static_assert(sizeof...(x) == 4);114 int a = x...[0];115 int b = x...[1];116 int c = x...[2];117 int d = x...[3];118}119 120template <typename T>121void lambda_capture() {122 auto [...x] = T{};123 [=] { (void)sum(x...); }();124 [&] { (void)sum(x...); }();125 [x...] { (void)sum(x...); }();126 [&x...] { (void)sum(x...); }();127}128 129struct S2 {130 int a, b, c;131};132 133auto X = [] <typename = void> () {134 auto [...pack] = S2{};135};136 137int main() {138 decompose_array<int>();139 decompose_tuple<fake_tuple>();140 decompose_struct<my_struct>();141 S<1, 2, 3, 4>::N<5, 6>().foo();142 decompose_bit_field<bit_fields>();143 lambda_capture<int[5]>();144 lambda_capture<fake_tuple>();145 lambda_capture<my_struct>();146 X();147 148}149 150// P1061R10 Stuff151namespace {152struct C { int x, y, z; };153 154template <class T>155void now_i_know_my() {156 auto [a, b, c] = C(); // OK, SB0 is a, SB1 is b, and SB2 is c157 auto [d, ...e] = C(); // OK, SB0 is d, the pack e (v1) contains two structured bindings: SB1 and SB2158 static_assert(sizeof...(e) == 2);159 auto [...f, g] = C(); // OK, the pack f (v0) contains two structured bindings: SB0 and SB1, and SB2 is g160 static_assert(sizeof...(e) == 2);161 auto [h, i, j, ...k] = C(); // OK, the pack k is empty162 static_assert(sizeof...(e) == 0);163 auto [l, m, n, o, ...p] = C(); // expected-error{{{binds to 3 elements, but 5 names were provided}}}164}165} // namespace166 167namespace {168auto g() -> int(&)[4];169 170template <unsigned long N>171void h(int (&arr)[N]) {172 auto [a, ...b, c] = arr; // a names the first element of the array,173 // b is a pack referring to the second and174 // third elements, and c names the fourth element175 static_assert(sizeof...(b) == 2);176 auto& [...e] = arr; // e is a pack referring to the four elements of the array177 static_assert(sizeof...(e) == 4);178}179 180void call_h() {181 h(g());182}183} // namespace184 185namespace {186struct D { };187 188int g(...) { return 1; }189 190template <typename T>191constexpr int f() {192 D arr[1];193 auto [...e] = arr;194 return g(e...);195}196 197constexpr int g(D) { return 2; }198 199void other_main() {200 static_assert(f<int>() == 2);201}202} // namespace203 204namespace {205struct S {206 int a,b,c;207};208 209clsss S2 { // expected-error{{{unknown type name 'clsss'}}}210public:211 int a,b,c;212};213 214// Should not crash.215auto X = [] <typename = void> () {216 auto [...pack,a,b,c] = S{};217 auto [x,y,z,...pack2] = S{};218 auto [...pack3] = S2{};219 static_assert(sizeof...(pack3) == 5);220};221} // namespace222 223namespace GH125165 {224 225template <typename = void>226auto f(auto t) {227 const auto& [...pack] = t;228 // expected-error@-1 {{cannot bind non-class, non-array type 'char const'}}229 (pack, ...);230};231 232void g() {233 f('x'); // expected-note {{in instantiation}}234}235 236}237 238namespace constant_interpreter {239using Arr = int[2];240struct Triple { int x, y, z = 3; };241 242constexpr int ref_to_same_obj(auto&& arg) {243 auto& [...xs] = arg;244 auto& [...ys] = arg;245 (..., (xs += 2));246 return sum(ys...);247}248static_assert(ref_to_same_obj(Arr{}) == 4);249static_assert(ref_to_same_obj(fake_tuple{}) == 20);250static_assert(ref_to_same_obj(Triple{}) == 9);251 252constexpr int copy_obj(auto&& arg) {253 auto& [...xs] = arg;254 auto [...ys] = arg;255 (..., (xs += 2));256 return sum(ys...);257}258static_assert(copy_obj(Arr{}) == 0);259static_assert(copy_obj(fake_tuple{}) == 12);260static_assert(copy_obj(Triple{}) == 3);261}262