xref: /llvm-project/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp (revision 050b064f15ee56ee0b42c9b957a3dd0f32532394)
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 // UNSUPPORTED: c++03, c++11, c++14
10 // UNSUPPORTED: libcpp-no-deduction-guides
11 // UNSUPPORTED: apple-clang-9
12 
13 // GCC's implementation of class template deduction is still immature and runs
14 // into issues with libc++. However GCC accepts this code when compiling
15 // against libstdc++.
16 // XFAIL: gcc-5, gcc-6, gcc-7, gcc-8, gcc-9, gcc-10, gcc-11
17 
18 // <tuple>
19 
20 // Test that the constructors offered by std::tuple are formulated
21 // so they're compatible with implicit deduction guides, or if that's not
22 // possible that they provide explicit guides to make it work.
23 
24 #include <tuple>
25 #include <cassert>
26 #include <functional>
27 #include <memory>
28 
29 #include "test_macros.h"
30 #include "archetypes.h"
31 
32 
33 // Overloads
34 //  using A = Allocator
35 //  using AT = std::allocator_arg_t
36 // ---------------
37 // (1)  tuple(const Types&...) -> tuple<Types...>
38 // (2)  tuple(pair<T1, T2>) -> tuple<T1, T2>;
39 // (3)  explicit tuple(const Types&...) -> tuple<Types...>
40 // (4)  tuple(AT, A const&, Types const&...) -> tuple<Types...>
41 // (5)  explicit tuple(AT, A const&, Types const&...) -> tuple<Types...>
42 // (6)  tuple(AT, A, pair<T1, T2>) -> tuple<T1, T2>
43 // (7)  tuple(tuple const& t) -> decltype(t)
44 // (8)  tuple(tuple&& t) -> decltype(t)
45 // (9)  tuple(AT, A const&, tuple const& t) -> decltype(t)
46 // (10) tuple(AT, A const&, tuple&& t) -> decltype(t)
47 void test_primary_template()
48 {
49   const std::allocator<int> A;
50   const auto AT = std::allocator_arg;
51   { // Testing (1)
52     int x = 101;
53     std::tuple t1(42);
54     ASSERT_SAME_TYPE(decltype(t1), std::tuple<int>);
55     std::tuple t2(x, 0.0, nullptr);
56     ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, double, decltype(nullptr)>);
57   }
58   { // Testing (2)
59     std::pair<int, char> p1(1, 'c');
60     std::tuple t1(p1);
61     ASSERT_SAME_TYPE(decltype(t1), std::tuple<int, char>);
62 
63     std::pair<int, std::tuple<char, long, void*>> p2(1, std::tuple<char, long, void*>('c', 3l, nullptr));
64     std::tuple t2(p2);
65     ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, std::tuple<char, long, void*>>);
66 
67     int i = 3;
68     std::pair<std::reference_wrapper<int>, char> p3(std::ref(i), 'c');
69     std::tuple t3(p3);
70     ASSERT_SAME_TYPE(decltype(t3), std::tuple<std::reference_wrapper<int>, char>);
71 
72     std::pair<int&, char> p4(i, 'c');
73     std::tuple t4(p4);
74     ASSERT_SAME_TYPE(decltype(t4), std::tuple<int&, char>);
75 
76     std::tuple t5(std::pair<int, char>(1, 'c'));
77     ASSERT_SAME_TYPE(decltype(t5), std::tuple<int, char>);
78   }
79   { // Testing (3)
80     using T = ExplicitTestTypes::TestType;
81     static_assert(!std::is_convertible<T const&, T>::value, "");
82 
83     std::tuple t1(T{});
84     ASSERT_SAME_TYPE(decltype(t1), std::tuple<T>);
85 
86     const T v{};
87     std::tuple t2(T{}, 101l, v);
88     ASSERT_SAME_TYPE(decltype(t2), std::tuple<T, long, T>);
89   }
90   { // Testing (4)
91     int x = 101;
92     std::tuple t1(AT, A, 42);
93     ASSERT_SAME_TYPE(decltype(t1), std::tuple<int>);
94 
95     std::tuple t2(AT, A, 42, 0.0, x);
96     ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, double, int>);
97   }
98   { // Testing (5)
99     using T = ExplicitTestTypes::TestType;
100     static_assert(!std::is_convertible<T const&, T>::value, "");
101 
102     std::tuple t1(AT, A, T{});
103     ASSERT_SAME_TYPE(decltype(t1), std::tuple<T>);
104 
105     const T v{};
106     std::tuple t2(AT, A, T{}, 101l, v);
107     ASSERT_SAME_TYPE(decltype(t2), std::tuple<T, long, T>);
108   }
109   { // Testing (6)
110     std::pair<int, char> p1(1, 'c');
111     std::tuple t1(AT, A, p1);
112     ASSERT_SAME_TYPE(decltype(t1), std::tuple<int, char>);
113 
114     std::pair<int, std::tuple<char, long, void*>> p2(1, std::tuple<char, long, void*>('c', 3l, nullptr));
115     std::tuple t2(AT, A, p2);
116     ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, std::tuple<char, long, void*>>);
117 
118     int i = 3;
119     std::pair<std::reference_wrapper<int>, char> p3(std::ref(i), 'c');
120     std::tuple t3(AT, A, p3);
121     ASSERT_SAME_TYPE(decltype(t3), std::tuple<std::reference_wrapper<int>, char>);
122 
123     std::pair<int&, char> p4(i, 'c');
124     std::tuple t4(AT, A, p4);
125     ASSERT_SAME_TYPE(decltype(t4), std::tuple<int&, char>);
126 
127     std::tuple t5(AT, A, std::pair<int, char>(1, 'c'));
128     ASSERT_SAME_TYPE(decltype(t5), std::tuple<int, char>);
129   }
130   { // Testing (7)
131     using Tup = std::tuple<int, decltype(nullptr)>;
132     const Tup t(42, nullptr);
133 
134     std::tuple t1(t);
135     ASSERT_SAME_TYPE(decltype(t1), Tup);
136   }
137   { // Testing (8)
138     using Tup = std::tuple<void*, unsigned, char>;
139     std::tuple t1(Tup(nullptr, 42, 'a'));
140     ASSERT_SAME_TYPE(decltype(t1), Tup);
141   }
142   { // Testing (9)
143     using Tup = std::tuple<int, decltype(nullptr)>;
144     const Tup t(42, nullptr);
145 
146     std::tuple t1(AT, A, t);
147     ASSERT_SAME_TYPE(decltype(t1), Tup);
148   }
149   { // Testing (10)
150     using Tup = std::tuple<void*, unsigned, char>;
151     std::tuple t1(AT, A, Tup(nullptr, 42, 'a'));
152     ASSERT_SAME_TYPE(decltype(t1), Tup);
153   }
154 }
155 
156 // Overloads
157 //  using A = Allocator
158 //  using AT = std::allocator_arg_t
159 // ---------------
160 // (1)  tuple() -> tuple<>
161 // (2)  tuple(AT, A const&) -> tuple<>
162 // (3)  tuple(tuple const&) -> tuple<>
163 // (4)  tuple(tuple&&) -> tuple<>
164 // (5)  tuple(AT, A const&, tuple const&) -> tuple<>
165 // (6)  tuple(AT, A const&, tuple&&) -> tuple<>
166 void test_empty_specialization()
167 {
168   std::allocator<int> A;
169   const auto AT = std::allocator_arg;
170   { // Testing (1)
171     std::tuple t1{};
172     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
173   }
174   { // Testing (2)
175     std::tuple t1{AT, A};
176     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
177   }
178   { // Testing (3)
179     const std::tuple<> t{};
180     std::tuple t1(t);
181     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
182   }
183   { // Testing (4)
184     std::tuple t1(std::tuple<>{});
185     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
186   }
187   { // Testing (5)
188     const std::tuple<> t{};
189     std::tuple t1(AT, A, t);
190     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
191   }
192   { // Testing (6)
193     std::tuple t1(AT, A, std::tuple<>{});
194     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
195   }
196 }
197 
198 int main(int, char**) {
199   test_primary_template();
200   test_empty_specialization();
201 
202   return 0;
203 }
204