103e29a29SEric Fiselier //===----------------------------------------------------------------------===//
203e29a29SEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
603e29a29SEric Fiselier //
703e29a29SEric Fiselier //===----------------------------------------------------------------------===//
803e29a29SEric Fiselier
9*31cbe0f2SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
1003e29a29SEric Fiselier
1103e29a29SEric Fiselier // <tuple>
1203e29a29SEric Fiselier
1303e29a29SEric Fiselier // template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);
1403e29a29SEric Fiselier
1503e29a29SEric Fiselier #include <tuple>
1603e29a29SEric Fiselier #include <array>
1703e29a29SEric Fiselier #include <utility>
1803e29a29SEric Fiselier #include <string>
1903e29a29SEric Fiselier #include <cassert>
2003e29a29SEric Fiselier
2103e29a29SEric Fiselier #include "test_macros.h"
2203e29a29SEric Fiselier #include "type_id.h"
2303e29a29SEric Fiselier
2403e29a29SEric Fiselier template <class Tuple>
2503e29a29SEric Fiselier struct ConstexprConstructibleFromTuple {
2603e29a29SEric Fiselier template <class ...Args>
ConstexprConstructibleFromTupleConstexprConstructibleFromTuple2703e29a29SEric Fiselier explicit constexpr ConstexprConstructibleFromTuple(Args&&... xargs)
2803e29a29SEric Fiselier : args{std::forward<Args>(xargs)...} {}
2903e29a29SEric Fiselier Tuple args;
3003e29a29SEric Fiselier };
3103e29a29SEric Fiselier
3203e29a29SEric Fiselier template <class TupleLike>
3303e29a29SEric Fiselier struct ConstructibleFromTuple;
3403e29a29SEric Fiselier
3503e29a29SEric Fiselier template <template <class ...> class Tuple, class ...Types>
3603e29a29SEric Fiselier struct ConstructibleFromTuple<Tuple<Types...>> {
3703e29a29SEric Fiselier template <class ...Args>
ConstructibleFromTupleConstructibleFromTuple3803e29a29SEric Fiselier explicit ConstructibleFromTuple(Args&&... xargs)
3903e29a29SEric Fiselier : args(xargs...),
4003e29a29SEric Fiselier arg_types(&makeArgumentID<Args&&...>())
4103e29a29SEric Fiselier {}
4203e29a29SEric Fiselier Tuple<std::decay_t<Types>...> args;
4303e29a29SEric Fiselier TypeID const* arg_types;
4403e29a29SEric Fiselier };
4503e29a29SEric Fiselier
4603e29a29SEric Fiselier template <class Tp, size_t N>
4703e29a29SEric Fiselier struct ConstructibleFromTuple<std::array<Tp, N>> {
4803e29a29SEric Fiselier template <class ...Args>
ConstructibleFromTupleConstructibleFromTuple4903e29a29SEric Fiselier explicit ConstructibleFromTuple(Args&&... xargs)
5003e29a29SEric Fiselier : args{xargs...},
5103e29a29SEric Fiselier arg_types(&makeArgumentID<Args&&...>())
5203e29a29SEric Fiselier {}
5303e29a29SEric Fiselier std::array<Tp, N> args;
5403e29a29SEric Fiselier TypeID const* arg_types;
5503e29a29SEric Fiselier };
5603e29a29SEric Fiselier
5703e29a29SEric Fiselier template <class Tuple>
do_constexpr_test(Tuple && tup)5803e29a29SEric Fiselier constexpr bool do_constexpr_test(Tuple&& tup) {
5903e29a29SEric Fiselier using RawTuple = std::decay_t<Tuple>;
6003e29a29SEric Fiselier using Tp = ConstexprConstructibleFromTuple<RawTuple>;
6103e29a29SEric Fiselier return std::make_from_tuple<Tp>(std::forward<Tuple>(tup)).args == tup;
6203e29a29SEric Fiselier }
6303e29a29SEric Fiselier
64881d8613SStephan T. Lavavej // Needed by do_forwarding_test() since it compares pairs of different types.
6503e29a29SEric Fiselier template <class T1, class T2, class U1, class U2>
operator ==(const std::pair<T1,T2> & lhs,const std::pair<U1,U2> & rhs)6603e29a29SEric Fiselier inline bool operator==(const std::pair<T1, T2>& lhs, const std::pair<U1, U2>& rhs) {
6703e29a29SEric Fiselier return lhs.first == rhs.first && lhs.second == rhs.second;
6803e29a29SEric Fiselier }
6903e29a29SEric Fiselier
7003e29a29SEric Fiselier template <class ...ExpectTypes, class Tuple>
do_forwarding_test(Tuple && tup)7103e29a29SEric Fiselier bool do_forwarding_test(Tuple&& tup) {
7203e29a29SEric Fiselier using RawTuple = std::decay_t<Tuple>;
7303e29a29SEric Fiselier using Tp = ConstructibleFromTuple<RawTuple>;
7403e29a29SEric Fiselier const Tp value = std::make_from_tuple<Tp>(std::forward<Tuple>(tup));
7503e29a29SEric Fiselier return value.args == tup
7603e29a29SEric Fiselier && value.arg_types == &makeArgumentID<ExpectTypes...>();
7703e29a29SEric Fiselier }
7803e29a29SEric Fiselier
test_constexpr_construction()7903e29a29SEric Fiselier void test_constexpr_construction() {
8003e29a29SEric Fiselier {
8103e29a29SEric Fiselier constexpr std::tuple<> tup;
8203e29a29SEric Fiselier static_assert(do_constexpr_test(tup), "");
8303e29a29SEric Fiselier }
8403e29a29SEric Fiselier {
8503e29a29SEric Fiselier constexpr std::tuple<int> tup(42);
8603e29a29SEric Fiselier static_assert(do_constexpr_test(tup), "");
8703e29a29SEric Fiselier }
8803e29a29SEric Fiselier {
8903e29a29SEric Fiselier constexpr std::tuple<int, long, void*> tup(42, 101, nullptr);
9003e29a29SEric Fiselier static_assert(do_constexpr_test(tup), "");
9103e29a29SEric Fiselier }
9203e29a29SEric Fiselier {
9303e29a29SEric Fiselier constexpr std::pair<int, const char*> p(42, "hello world");
9403e29a29SEric Fiselier static_assert(do_constexpr_test(p), "");
9503e29a29SEric Fiselier }
9603e29a29SEric Fiselier {
9703e29a29SEric Fiselier using Tuple = std::array<int, 3>;
9803e29a29SEric Fiselier using ValueTp = ConstexprConstructibleFromTuple<Tuple>;
9903e29a29SEric Fiselier constexpr Tuple arr = {42, 101, -1};
10003e29a29SEric Fiselier constexpr ValueTp value = std::make_from_tuple<ValueTp>(arr);
10103e29a29SEric Fiselier static_assert(value.args[0] == arr[0] && value.args[1] == arr[1]
10203e29a29SEric Fiselier && value.args[2] == arr[2], "");
10303e29a29SEric Fiselier }
10403e29a29SEric Fiselier }
10503e29a29SEric Fiselier
test_perfect_forwarding()10603e29a29SEric Fiselier void test_perfect_forwarding() {
10703e29a29SEric Fiselier {
10803e29a29SEric Fiselier using Tup = std::tuple<>;
10903e29a29SEric Fiselier Tup tup;
11003e29a29SEric Fiselier Tup const& ctup = tup;
11103e29a29SEric Fiselier assert(do_forwarding_test<>(tup));
11203e29a29SEric Fiselier assert(do_forwarding_test<>(ctup));
11303e29a29SEric Fiselier }
11403e29a29SEric Fiselier {
11503e29a29SEric Fiselier using Tup = std::tuple<int>;
11603e29a29SEric Fiselier Tup tup(42);
11703e29a29SEric Fiselier Tup const& ctup = tup;
11803e29a29SEric Fiselier assert(do_forwarding_test<int&>(tup));
11903e29a29SEric Fiselier assert(do_forwarding_test<int const&>(ctup));
12003e29a29SEric Fiselier assert(do_forwarding_test<int&&>(std::move(tup)));
12103e29a29SEric Fiselier assert(do_forwarding_test<int const&&>(std::move(ctup)));
12203e29a29SEric Fiselier }
12303e29a29SEric Fiselier {
12403e29a29SEric Fiselier using Tup = std::tuple<int&, const char*, unsigned&&>;
12503e29a29SEric Fiselier int x = 42;
12603e29a29SEric Fiselier unsigned y = 101;
12703e29a29SEric Fiselier Tup tup(x, "hello world", std::move(y));
12803e29a29SEric Fiselier Tup const& ctup = tup;
12903e29a29SEric Fiselier assert((do_forwarding_test<int&, const char*&, unsigned&>(tup)));
13003e29a29SEric Fiselier assert((do_forwarding_test<int&, const char* const&, unsigned &>(ctup)));
13103e29a29SEric Fiselier assert((do_forwarding_test<int&, const char*&&, unsigned&&>(std::move(tup))));
13203e29a29SEric Fiselier assert((do_forwarding_test<int&, const char* const&&, unsigned &&>(std::move(ctup))));
13303e29a29SEric Fiselier }
13403e29a29SEric Fiselier // test with pair<T, U>
13503e29a29SEric Fiselier {
13603e29a29SEric Fiselier using Tup = std::pair<int&, const char*>;
13703e29a29SEric Fiselier int x = 42;
13803e29a29SEric Fiselier Tup tup(x, "hello world");
13903e29a29SEric Fiselier Tup const& ctup = tup;
14003e29a29SEric Fiselier assert((do_forwarding_test<int&, const char*&>(tup)));
14103e29a29SEric Fiselier assert((do_forwarding_test<int&, const char* const&>(ctup)));
14203e29a29SEric Fiselier assert((do_forwarding_test<int&, const char*&&>(std::move(tup))));
14303e29a29SEric Fiselier assert((do_forwarding_test<int&, const char* const&&>(std::move(ctup))));
14403e29a29SEric Fiselier }
14503e29a29SEric Fiselier // test with array<T, I>
14603e29a29SEric Fiselier {
14703e29a29SEric Fiselier using Tup = std::array<int, 3>;
14803e29a29SEric Fiselier Tup tup = {42, 101, -1};
14903e29a29SEric Fiselier Tup const& ctup = tup;
15003e29a29SEric Fiselier assert((do_forwarding_test<int&, int&, int&>(tup)));
15103e29a29SEric Fiselier assert((do_forwarding_test<int const&, int const&, int const&>(ctup)));
15203e29a29SEric Fiselier assert((do_forwarding_test<int&&, int&&, int&&>(std::move(tup))));
15303e29a29SEric Fiselier assert((do_forwarding_test<int const&&, int const&&, int const&&>(std::move(ctup))));
15403e29a29SEric Fiselier }
15503e29a29SEric Fiselier }
15603e29a29SEric Fiselier
test_noexcept()15703e29a29SEric Fiselier void test_noexcept() {
15803e29a29SEric Fiselier struct NothrowMoveable {
15903e29a29SEric Fiselier NothrowMoveable() = default;
16003e29a29SEric Fiselier NothrowMoveable(NothrowMoveable const&) {}
16103e29a29SEric Fiselier NothrowMoveable(NothrowMoveable&&) noexcept {}
16203e29a29SEric Fiselier };
16303e29a29SEric Fiselier struct TestType {
16403e29a29SEric Fiselier TestType(int, NothrowMoveable) noexcept {}
16503e29a29SEric Fiselier TestType(int, int, int) noexcept(false) {}
16603e29a29SEric Fiselier TestType(long, long, long) noexcept {}
16703e29a29SEric Fiselier };
16803e29a29SEric Fiselier {
16903e29a29SEric Fiselier using Tuple = std::tuple<int, NothrowMoveable>;
17003e29a29SEric Fiselier Tuple tup; ((void)tup);
17103e29a29SEric Fiselier Tuple const& ctup = tup; ((void)ctup);
17203e29a29SEric Fiselier ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(ctup));
1738a597d65SStephan T. Lavavej LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup)));
17403e29a29SEric Fiselier }
17503e29a29SEric Fiselier {
17603e29a29SEric Fiselier using Tuple = std::pair<int, NothrowMoveable>;
17703e29a29SEric Fiselier Tuple tup; ((void)tup);
17803e29a29SEric Fiselier Tuple const& ctup = tup; ((void)ctup);
17903e29a29SEric Fiselier ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(ctup));
1808a597d65SStephan T. Lavavej LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup)));
18103e29a29SEric Fiselier }
18203e29a29SEric Fiselier {
18303e29a29SEric Fiselier using Tuple = std::tuple<int, int, int>;
18403e29a29SEric Fiselier Tuple tup; ((void)tup);
18503e29a29SEric Fiselier ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
18603e29a29SEric Fiselier }
18703e29a29SEric Fiselier {
18803e29a29SEric Fiselier using Tuple = std::tuple<long, long, long>;
18903e29a29SEric Fiselier Tuple tup; ((void)tup);
1908a597d65SStephan T. Lavavej LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
19103e29a29SEric Fiselier }
19203e29a29SEric Fiselier {
19303e29a29SEric Fiselier using Tuple = std::array<int, 3>;
19403e29a29SEric Fiselier Tuple tup; ((void)tup);
19503e29a29SEric Fiselier ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
19603e29a29SEric Fiselier }
19703e29a29SEric Fiselier {
19803e29a29SEric Fiselier using Tuple = std::array<long, 3>;
19903e29a29SEric Fiselier Tuple tup; ((void)tup);
2008a597d65SStephan T. Lavavej LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup));
20103e29a29SEric Fiselier }
20203e29a29SEric Fiselier }
20303e29a29SEric Fiselier
main(int,char **)2042df59c50SJF Bastien int main(int, char**)
20503e29a29SEric Fiselier {
20603e29a29SEric Fiselier test_constexpr_construction();
20703e29a29SEric Fiselier test_perfect_forwarding();
20803e29a29SEric Fiselier test_noexcept();
2092df59c50SJF Bastien
2102df59c50SJF Bastien return 0;
21103e29a29SEric Fiselier }
212