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 | |
26 | struct S { int x; }; |
27 | |
28 | void 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 | |
45 | void 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 | |
64 | void 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 | |
86 | void 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 | |
112 | struct Test { |
113 | int x; |
114 | }; |
115 | |
116 | template <std::size_t N> |
117 | int get(Test const&) { static_assert(N == 0, "" ); return -1; } |
118 | |
119 | template <> |
120 | struct std::tuple_element<0, Test> { |
121 | typedef int type; |
122 | }; |
123 | |
124 | void test_before_tuple_size_specialization() { |
125 | Test const t{.x: 99}; |
126 | auto& [p] = t; |
127 | assert(p == 99); |
128 | } |
129 | |
130 | template <> |
131 | struct std::tuple_size<Test> { |
132 | public: |
133 | static const std::size_t value = 1; |
134 | }; |
135 | |
136 | void test_after_tuple_size_specialization() { |
137 | Test const t{.x: 99}; |
138 | auto& [p] = t; |
139 | assert(p == -1); |
140 | } |
141 | |
142 | int main(int, char**) { |
143 | test_decomp_user_type(); |
144 | test_decomp_tuple(); |
145 | test_decomp_pair(); |
146 | test_decomp_array(); |
147 | test_before_tuple_size_specialization(); |
148 | test_after_tuple_size_specialization(); |
149 | |
150 | return 0; |
151 | } |
152 | |