xref: /llvm-project/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp (revision b4aebff4f1a6891c31f4f3bb54cdd42c00d5112a)
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++98, 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
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 <memory>
26 #include <cassert>
27 
28 #include "test_macros.h"
29 #include "archetypes.hpp"
30 
31 
32 // Overloads
33 //  using A = Allocator
34 //  using AT = std::allocator_arg_t
35 // ---------------
36 // (1)  tuple(const Types&...) -> tuple<Types...>
37 // (2)  tuple(pair<T1, T2>) -> tuple<T1, T2>;
38 // (3)  explicit tuple(const Types&...) -> tuple<Types...>
39 // (4)  tuple(AT, A const&, Types const&...) -> tuple<Types...>
40 // (5)  explicit tuple(AT, A const&, Types const&...) -> tuple<Types...>
41 // (6)  tuple(AT, A, pair<T1, T2>) -> tuple<T1, T2>
42 // (7)  tuple(tuple const& t) -> decltype(t)
43 // (8)  tuple(tuple&& t) -> decltype(t)
44 // (9)  tuple(AT, A const&, tuple const& t) -> decltype(t)
45 // (10) tuple(AT, A const&, tuple&& t) -> decltype(t)
46 void test_primary_template()
47 {
48   const std::allocator<int> A;
49   const auto AT = std::allocator_arg;
50   { // Testing (1)
51     int x = 101;
52     std::tuple t1(42);
53     ASSERT_SAME_TYPE(decltype(t1), std::tuple<int>);
54     std::tuple t2(x, 0.0, nullptr);
55     ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, double, decltype(nullptr)>);
56   }
57   { // Testing (2)
58     std::pair<int, char> p1(1, 'c');
59     std::tuple t1(p1);
60     ASSERT_SAME_TYPE(decltype(t1), std::tuple<int, char>);
61 
62     std::pair<int, std::tuple<char, long, void*>> p2(1, std::tuple<char, long, void*>('c', 3l, nullptr));
63     std::tuple t2(p2);
64     ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, std::tuple<char, long, void*>>);
65 
66     int i = 3;
67     std::pair<std::reference_wrapper<int>, char> p3(std::ref(i), 'c');
68     std::tuple t3(p3);
69     ASSERT_SAME_TYPE(decltype(t3), std::tuple<std::reference_wrapper<int>, char>);
70 
71     std::pair<int&, char> p4(i, 'c');
72     std::tuple t4(p4);
73     ASSERT_SAME_TYPE(decltype(t4), std::tuple<int&, char>);
74 
75     std::tuple t5(std::pair<int, char>(1, 'c'));
76     ASSERT_SAME_TYPE(decltype(t5), std::tuple<int, char>);
77   }
78   { // Testing (3)
79     using T = ExplicitTestTypes::TestType;
80     static_assert(!std::is_convertible<T const&, T>::value, "");
81 
82     std::tuple t1(T{});
83     ASSERT_SAME_TYPE(decltype(t1), std::tuple<T>);
84 
85     const T v{};
86     std::tuple t2(T{}, 101l, v);
87     ASSERT_SAME_TYPE(decltype(t2), std::tuple<T, long, T>);
88   }
89   { // Testing (4)
90     int x = 101;
91     std::tuple t1(AT, A, 42);
92     ASSERT_SAME_TYPE(decltype(t1), std::tuple<int>);
93 
94     std::tuple t2(AT, A, 42, 0.0, x);
95     ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, double, int>);
96   }
97   { // Testing (5)
98     using T = ExplicitTestTypes::TestType;
99     static_assert(!std::is_convertible<T const&, T>::value, "");
100 
101     std::tuple t1(AT, A, T{});
102     ASSERT_SAME_TYPE(decltype(t1), std::tuple<T>);
103 
104     const T v{};
105     std::tuple t2(AT, A, T{}, 101l, v);
106     ASSERT_SAME_TYPE(decltype(t2), std::tuple<T, long, T>);
107   }
108   { // Testing (6)
109     std::pair<int, char> p1(1, 'c');
110     std::tuple t1(AT, A, p1);
111     ASSERT_SAME_TYPE(decltype(t1), std::tuple<int, char>);
112 
113     std::pair<int, std::tuple<char, long, void*>> p2(1, std::tuple<char, long, void*>('c', 3l, nullptr));
114     std::tuple t2(AT, A, p2);
115     ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, std::tuple<char, long, void*>>);
116 
117     int i = 3;
118     std::pair<std::reference_wrapper<int>, char> p3(std::ref(i), 'c');
119     std::tuple t3(AT, A, p3);
120     ASSERT_SAME_TYPE(decltype(t3), std::tuple<std::reference_wrapper<int>, char>);
121 
122     std::pair<int&, char> p4(i, 'c');
123     std::tuple t4(AT, A, p4);
124     ASSERT_SAME_TYPE(decltype(t4), std::tuple<int&, char>);
125 
126     std::tuple t5(AT, A, std::pair<int, char>(1, 'c'));
127     ASSERT_SAME_TYPE(decltype(t5), std::tuple<int, char>);
128   }
129   { // Testing (7)
130     using Tup = std::tuple<int, decltype(nullptr)>;
131     const Tup t(42, nullptr);
132 
133     std::tuple t1(t);
134     ASSERT_SAME_TYPE(decltype(t1), Tup);
135   }
136   { // Testing (8)
137     using Tup = std::tuple<void*, unsigned, char>;
138     std::tuple t1(Tup(nullptr, 42, 'a'));
139     ASSERT_SAME_TYPE(decltype(t1), Tup);
140   }
141   { // Testing (9)
142     using Tup = std::tuple<int, decltype(nullptr)>;
143     const Tup t(42, nullptr);
144 
145     std::tuple t1(AT, A, t);
146     ASSERT_SAME_TYPE(decltype(t1), Tup);
147   }
148   { // Testing (10)
149     using Tup = std::tuple<void*, unsigned, char>;
150     std::tuple t1(AT, A, Tup(nullptr, 42, 'a'));
151     ASSERT_SAME_TYPE(decltype(t1), Tup);
152   }
153 }
154 
155 // Overloads
156 //  using A = Allocator
157 //  using AT = std::allocator_arg_t
158 // ---------------
159 // (1)  tuple() -> tuple<>
160 // (2)  tuple(AT, A const&) -> tuple<>
161 // (3)  tuple(tuple const&) -> tuple<>
162 // (4)  tuple(tuple&&) -> tuple<>
163 // (5)  tuple(AT, A const&, tuple const&) -> tuple<>
164 // (6)  tuple(AT, A const&, tuple&&) -> tuple<>
165 void test_empty_specialization()
166 {
167   std::allocator<int> A;
168   const auto AT = std::allocator_arg;
169   { // Testing (1)
170     std::tuple t1{};
171     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
172   }
173   { // Testing (2)
174     std::tuple t1{AT, A};
175     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
176   }
177   { // Testing (3)
178     const std::tuple<> t{};
179     std::tuple t1(t);
180     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
181   }
182   { // Testing (4)
183     std::tuple t1(std::tuple<>{});
184     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
185   }
186   { // Testing (5)
187     const std::tuple<> t{};
188     std::tuple t1(AT, A, t);
189     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
190   }
191   { // Testing (6)
192     std::tuple t1(AT, A, std::tuple<>{});
193     ASSERT_SAME_TYPE(decltype(t1), std::tuple<>);
194   }
195 }
196 
197 int main(int, char**) {
198   test_primary_template();
199   test_empty_specialization();
200 
201   return 0;
202 }
203