1 //===----------------------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // UNSUPPORTED: c++98, c++03, c++11, c++14
14 // template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);
22 #include "test_macros.h"
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"
29 template <class Tuple>
30 struct ConstexprConstructibleFromTuple {
31 template <class ...Args>
32 explicit constexpr ConstexprConstructibleFromTuple(Args&&... xargs)
33 : args{std::forward<Args>(xargs)...} {}
37 template <class TupleLike>
38 struct ConstructibleFromTuple;
40 template <template <class ...> class Tuple, class ...Types>
41 struct ConstructibleFromTuple<Tuple<Types...>> {
42 template <class ...Args>
43 explicit ConstructibleFromTuple(Args&&... xargs)
45 arg_types(&makeArgumentID<Args&&...>())
47 Tuple<std::decay_t<Types>...> args;
48 TypeID const* arg_types;
51 template <class Tp, size_t N>
52 struct ConstructibleFromTuple<std::array<Tp, N>> {
53 template <class ...Args>
54 explicit ConstructibleFromTuple(Args&&... xargs)
56 arg_types(&makeArgumentID<Args&&...>())
58 std::array<Tp, N> args;
59 TypeID const* arg_types;
62 template <class Tuple>
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;
69 // Needed by do_forwarding_test() since it compare pairs of different types.
70 template <class T1, class T2, class U1, class U2>
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;
75 template <class ...ExpectTypes, class Tuple>
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...>();
84 void test_constexpr_construction() {
86 constexpr std::tuple<> tup;
87 static_assert(do_constexpr_test(tup), "");
90 constexpr std::tuple<int> tup(42);
91 static_assert(do_constexpr_test(tup), "");
94 constexpr std::tuple<int, long, void*> tup(42, 101, nullptr);
95 static_assert(do_constexpr_test(tup), "");
98 constexpr std::pair<int, const char*> p(42, "hello world");
99 static_assert(do_constexpr_test(p), "");
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], "");
111 void test_perfect_forwarding() {
113 using Tup = std::tuple<>;
115 Tup const& ctup = tup;
116 assert(do_forwarding_test<>(tup));
117 assert(do_forwarding_test<>(ctup));
120 using Tup = std::tuple<int>;
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)));
129 using Tup = std::tuple<int&, const char*, unsigned&&>;
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))));
139 // test with pair<T, U>
141 using Tup = std::pair<int&, const char*>;
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))));
150 // test with array<T, I>
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))));
162 void test_noexcept() {
163 struct NothrowMoveable {
164 NothrowMoveable() = default;
165 NothrowMoveable(NothrowMoveable const&) {}
166 NothrowMoveable(NothrowMoveable&&) noexcept {}
169 TestType(int, NothrowMoveable) noexcept {}
170 TestType(int, int, int) noexcept(false) {}
171 TestType(long, long, long) noexcept {}
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)));
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)));
188 using Tuple = std::tuple<int, int, int>;
189 Tuple tup; ((void)tup);
190 ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
193 using Tuple = std::tuple<long, long, long>;
194 Tuple tup; ((void)tup);
195 LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
198 using Tuple = std::array<int, 3>;
199 Tuple tup; ((void)tup);
200 ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
203 using Tuple = std::array<long, 3>;
204 Tuple tup; ((void)tup);
205 LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
211 test_constexpr_construction();
212 test_perfect_forwarding();