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