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... Types>
14// struct tuple_size<tuple<Types...>>
15// : public integral_constant<size_t, sizeof...(Types)> { };
16
17// UNSUPPORTED: c++03, c++11, c++14
18
19#include <array>
20#include <cassert>
21#include <tuple>
22#include <utility>
23
24#include "test_macros.h"
25
26struct S { int x; };
27
28void test_decomp_user_type() {
29 {
30 S s{.x: 99};
31 auto [m1] = s;
32 auto& [r1] = s;
33 assert(m1 == 99);
34 assert(&r1 == &s.x);
35 }
36 {
37 S const s{.x: 99};
38 auto [m1] = s;
39 auto& [r1] = s;
40 assert(m1 == 99);
41 assert(&r1 == &s.x);
42 }
43}
44
45void test_decomp_tuple() {
46 typedef std::tuple<int> T;
47 {
48 T s{99};
49 auto [m1] = s;
50 auto& [r1] = s;
51 assert(m1 == 99);
52 assert(&r1 == &std::get<0>(s));
53 }
54 {
55 T const s{99};
56 auto [m1] = s;
57 auto& [r1] = s;
58 assert(m1 == 99);
59 assert(&r1 == &std::get<0>(s));
60 }
61}
62
63
64void test_decomp_pair() {
65 typedef std::pair<int, double> T;
66 {
67 T s{99, 42.5};
68 auto [m1, m2] = s;
69 auto& [r1, r2] = s;
70 assert(m1 == 99);
71 assert(m2 == 42.5);
72 assert(&r1 == &std::get<0>(s));
73 assert(&r2 == &std::get<1>(s));
74 }
75 {
76 T const s{99, 42.5};
77 auto [m1, m2] = s;
78 auto& [r1, r2] = s;
79 assert(m1 == 99);
80 assert(m2 == 42.5);
81 assert(&r1 == &std::get<0>(s));
82 assert(&r2 == &std::get<1>(s));
83 }
84}
85
86void test_decomp_array() {
87 typedef std::array<int, 3> T;
88 {
89 T s{._M_elems: {99, 42, -1}};
90 auto [m1, m2, m3] = s;
91 auto& [r1, r2, r3] = s;
92 assert(m1 == 99);
93 assert(m2 == 42);
94 assert(m3 == -1);
95 assert(&r1 == &std::get<0>(s));
96 assert(&r2 == &std::get<1>(s));
97 assert(&r3 == &std::get<2>(s));
98 }
99 {
100 T const s{._M_elems: {99, 42, -1}};
101 auto [m1, m2, m3] = s;
102 auto& [r1, r2, r3] = s;
103 assert(m1 == 99);
104 assert(m2 == 42);
105 assert(m3 == -1);
106 assert(&r1 == &std::get<0>(s));
107 assert(&r2 == &std::get<1>(s));
108 assert(&r3 == &std::get<2>(s));
109 }
110}
111
112struct TestLWG2770 {
113 int n;
114};
115
116template <>
117struct std::tuple_size<TestLWG2770> {};
118
119void test_lwg_2770() {
120 {
121 auto [n] = TestLWG2770{.n: 42};
122 assert(n == 42);
123 }
124 {
125 const auto [n] = TestLWG2770{.n: 42};
126 assert(n == 42);
127 }
128 {
129 TestLWG2770 s{.n: 42};
130 auto& [n] = s;
131 assert(n == 42);
132 assert(&n == &s.n);
133 }
134 {
135 const TestLWG2770 s{.n: 42};
136 auto& [n] = s;
137 assert(n == 42);
138 assert(&n == &s.n);
139 }
140}
141
142struct Test {
143 int x;
144};
145
146template <std::size_t N>
147int get(Test const&) { static_assert(N == 0, ""); return -1; }
148
149template <>
150struct std::tuple_element<0, Test> {
151 typedef int type;
152};
153
154void test_before_tuple_size_specialization() {
155 Test const t{.x: 99};
156 auto& [p] = t;
157 assert(p == 99);
158}
159
160template <>
161struct std::tuple_size<Test> {
162public:
163 static const std::size_t value = 1;
164};
165
166void test_after_tuple_size_specialization() {
167 Test const t{.x: 99};
168 auto& [p] = t;
169 // https://cplusplus.github.io/LWG/issue4040
170 // It is controversial whether std::tuple_size<const Test> is instantiated here or before.
171 (void)p;
172 LIBCPP_ASSERT(p == -1);
173}
174
175#if TEST_STD_VER >= 26 && __cpp_structured_bindings >= 202411L
176struct InvalidWhenNoCv1 {};
177
178template <>
179struct std::tuple_size<InvalidWhenNoCv1> {};
180
181struct InvalidWhenNoCv2 {};
182
183template <>
184struct std::tuple_size<InvalidWhenNoCv2> {
185 void value();
186};
187
188template <class = void>
189void test_decomp_as_empty_pack() {
190 {
191 const auto [... pack] = InvalidWhenNoCv1{};
192 static_assert(sizeof...(pack) == 0);
193 }
194 {
195 const auto [... pack] = InvalidWhenNoCv2{};
196 static_assert(sizeof...(pack) == 0);
197 }
198}
199#endif
200
201int main(int, char**) {
202 test_decomp_user_type();
203 test_decomp_tuple();
204 test_decomp_pair();
205 test_decomp_array();
206 test_lwg_2770();
207 test_before_tuple_size_specialization();
208 test_after_tuple_size_specialization();
209#if TEST_STD_VER >= 26 && __cpp_structured_bindings >= 202411L
210 test_decomp_as_empty_pack();
211#endif
212
213 return 0;
214}
215

source code of libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp