• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // UNSUPPORTED: c++98, c++03, c++11, c++14
11 
12 // <tuple>
13 
14 // template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);
15 
16 #include <tuple>
17 #include <array>
18 #include <utility>
19 #include <string>
20 #include <cassert>
21 
22 #include "test_macros.h"
23 #include "type_id.h"
24 
25 // std::array is explicitly allowed to be initialized with A a = { init-list };.
26 // Disable the missing braces warning for this reason.
27 #include "disable_missing_braces_warning.h"
28 
29 template <class Tuple>
30 struct ConstexprConstructibleFromTuple {
31   template <class ...Args>
ConstexprConstructibleFromTupleConstexprConstructibleFromTuple32   explicit constexpr ConstexprConstructibleFromTuple(Args&&... xargs)
33       : args{std::forward<Args>(xargs)...} {}
34   Tuple args;
35 };
36 
37 template <class TupleLike>
38 struct ConstructibleFromTuple;
39 
40 template <template <class ...> class Tuple, class ...Types>
41 struct ConstructibleFromTuple<Tuple<Types...>> {
42   template <class ...Args>
ConstructibleFromTupleConstructibleFromTuple43   explicit ConstructibleFromTuple(Args&&... xargs)
44       : args(xargs...),
45         arg_types(&makeArgumentID<Args&&...>())
46   {}
47   Tuple<std::decay_t<Types>...> args;
48   TypeID const* arg_types;
49 };
50 
51 template <class Tp, size_t N>
52 struct ConstructibleFromTuple<std::array<Tp, N>> {
53 template <class ...Args>
ConstructibleFromTupleConstructibleFromTuple54   explicit ConstructibleFromTuple(Args&&... xargs)
55       : args{xargs...},
56         arg_types(&makeArgumentID<Args&&...>())
57   {}
58   std::array<Tp, N> args;
59   TypeID const* arg_types;
60 };
61 
62 template <class Tuple>
do_constexpr_test(Tuple && tup)63 constexpr bool do_constexpr_test(Tuple&& tup) {
64     using RawTuple = std::decay_t<Tuple>;
65     using Tp = ConstexprConstructibleFromTuple<RawTuple>;
66     return std::make_from_tuple<Tp>(std::forward<Tuple>(tup)).args == tup;
67 }
68 
69 // Needed by do_forwarding_test() since it compares pairs of different types.
70 template <class T1, class T2, class U1, class U2>
operator ==(const std::pair<T1,T2> & lhs,const std::pair<U1,U2> & rhs)71 inline bool operator==(const std::pair<T1, T2>& lhs, const std::pair<U1, U2>& rhs) {
72     return lhs.first == rhs.first && lhs.second == rhs.second;
73 }
74 
75 template <class ...ExpectTypes, class Tuple>
do_forwarding_test(Tuple && tup)76 bool do_forwarding_test(Tuple&& tup) {
77     using RawTuple = std::decay_t<Tuple>;
78     using Tp = ConstructibleFromTuple<RawTuple>;
79     const Tp value = std::make_from_tuple<Tp>(std::forward<Tuple>(tup));
80     return value.args == tup
81         && value.arg_types == &makeArgumentID<ExpectTypes...>();
82 }
83 
test_constexpr_construction()84 void test_constexpr_construction() {
85     {
86         constexpr std::tuple<> tup;
87         static_assert(do_constexpr_test(tup), "");
88     }
89     {
90         constexpr std::tuple<int> tup(42);
91         static_assert(do_constexpr_test(tup), "");
92     }
93     {
94         constexpr std::tuple<int, long, void*> tup(42, 101, nullptr);
95         static_assert(do_constexpr_test(tup), "");
96     }
97     {
98         constexpr std::pair<int, const char*> p(42, "hello world");
99         static_assert(do_constexpr_test(p), "");
100     }
101     {
102         using Tuple = std::array<int, 3>;
103         using ValueTp = ConstexprConstructibleFromTuple<Tuple>;
104         constexpr Tuple arr = {42, 101, -1};
105         constexpr ValueTp value = std::make_from_tuple<ValueTp>(arr);
106         static_assert(value.args[0] == arr[0] && value.args[1] == arr[1]
107             && value.args[2] == arr[2], "");
108     }
109 }
110 
test_perfect_forwarding()111 void test_perfect_forwarding() {
112     {
113         using Tup = std::tuple<>;
114         Tup tup;
115         Tup const& ctup = tup;
116         assert(do_forwarding_test<>(tup));
117         assert(do_forwarding_test<>(ctup));
118     }
119     {
120         using Tup = std::tuple<int>;
121         Tup tup(42);
122         Tup const& ctup = tup;
123         assert(do_forwarding_test<int&>(tup));
124         assert(do_forwarding_test<int const&>(ctup));
125         assert(do_forwarding_test<int&&>(std::move(tup)));
126         assert(do_forwarding_test<int const&&>(std::move(ctup)));
127     }
128     {
129         using Tup = std::tuple<int&, const char*, unsigned&&>;
130         int x = 42;
131         unsigned y = 101;
132         Tup tup(x, "hello world", std::move(y));
133         Tup const& ctup = tup;
134         assert((do_forwarding_test<int&, const char*&, unsigned&>(tup)));
135         assert((do_forwarding_test<int&, const char* const&, unsigned &>(ctup)));
136         assert((do_forwarding_test<int&, const char*&&, unsigned&&>(std::move(tup))));
137         assert((do_forwarding_test<int&, const char* const&&, unsigned &&>(std::move(ctup))));
138     }
139     // test with pair<T, U>
140     {
141         using Tup = std::pair<int&, const char*>;
142         int x = 42;
143         Tup tup(x, "hello world");
144         Tup const& ctup = tup;
145         assert((do_forwarding_test<int&, const char*&>(tup)));
146         assert((do_forwarding_test<int&, const char* const&>(ctup)));
147         assert((do_forwarding_test<int&, const char*&&>(std::move(tup))));
148         assert((do_forwarding_test<int&, const char* const&&>(std::move(ctup))));
149     }
150     // test with array<T, I>
151     {
152         using Tup = std::array<int, 3>;
153         Tup tup = {42, 101, -1};
154         Tup const& ctup = tup;
155         assert((do_forwarding_test<int&, int&, int&>(tup)));
156         assert((do_forwarding_test<int const&, int const&, int const&>(ctup)));
157         assert((do_forwarding_test<int&&, int&&, int&&>(std::move(tup))));
158         assert((do_forwarding_test<int const&&, int const&&, int const&&>(std::move(ctup))));
159     }
160 }
161 
test_noexcept()162 void test_noexcept() {
163     struct NothrowMoveable {
164       NothrowMoveable() = default;
165       NothrowMoveable(NothrowMoveable const&) {}
166       NothrowMoveable(NothrowMoveable&&) noexcept {}
167     };
168     struct TestType {
169       TestType(int, NothrowMoveable) noexcept {}
170       TestType(int, int, int) noexcept(false) {}
171       TestType(long, long, long) noexcept {}
172     };
173     {
174         using Tuple = std::tuple<int, NothrowMoveable>;
175         Tuple tup; ((void)tup);
176         Tuple const& ctup = tup; ((void)ctup);
177         ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(ctup));
178         LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup)));
179     }
180     {
181         using Tuple = std::pair<int, NothrowMoveable>;
182         Tuple tup; ((void)tup);
183         Tuple const& ctup = tup; ((void)ctup);
184         ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(ctup));
185         LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup)));
186     }
187     {
188         using Tuple = std::tuple<int, int, int>;
189         Tuple tup; ((void)tup);
190         ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
191     }
192     {
193         using Tuple = std::tuple<long, long, long>;
194         Tuple tup; ((void)tup);
195         LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
196     }
197     {
198         using Tuple = std::array<int, 3>;
199         Tuple tup; ((void)tup);
200         ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
201     }
202     {
203         using Tuple = std::array<long, 3>;
204         Tuple tup; ((void)tup);
205         LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
206     }
207 }
208 
main()209 int main()
210 {
211     test_constexpr_construction();
212     test_perfect_forwarding();
213     test_noexcept();
214 }
215