1f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier//===----------------------------------------------------------------------===//
2f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier//
3f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier//                     The LLVM Compiler Infrastructure
4f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier//
5f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// This file is dual licensed under the MIT and the University of Illinois Open
6f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// Source Licenses. See LICENSE.TXT for details.
7f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier//
8f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier//===----------------------------------------------------------------------===//
9f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
10f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// <tuple>
11f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
12f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// template <class... Types> class tuple;
13f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
14f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// template <class... UTypes>
15f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier//   explicit tuple(UTypes&&... u);
16f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
17f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// UNSUPPORTED: c++98, c++03
18f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
19f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// MODULES_DEFINES: _LIBCPP_ENABLE_TUPLE_IMPLICIT_REDUCED_ARITY_EXTENSION
20f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier#define _LIBCPP_ENABLE_TUPLE_IMPLICIT_REDUCED_ARITY_EXTENSION
21f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier#include <tuple>
22f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier#include <cassert>
23f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier#include <type_traits>
24f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier#include <string>
25f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier#include <system_error>
26f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
27f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier#include "test_macros.h"
28f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier#include "test_convertible.hpp"
29f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier#include "MoveOnly.h"
30f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
31f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
32f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselierstruct NoDefault { NoDefault() = delete; };
33f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
34f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
35f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// Make sure the _Up... constructor SFINAEs out when the types that
36f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// are not explicitly initialized are not all default constructible.
37f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// Otherwise, std::is_constructible would return true but instantiating
38f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// the constructor would fail.
39f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiseliervoid test_default_constructible_extension_sfinae()
40f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier{
41f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    typedef MoveOnly MO;
42f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    typedef NoDefault ND;
43f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    {
44f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        typedef std::tuple<MO, ND> Tuple;
45f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(!std::is_constructible<Tuple, MO>::value, "");
46f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(std::is_constructible<Tuple, MO, ND>::value, "");
47f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(test_convertible<Tuple, MO, ND>(), "");
48f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    }
49f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    {
50f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        typedef std::tuple<MO, MO, ND> Tuple;
51f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(!std::is_constructible<Tuple, MO, MO>::value, "");
52f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(std::is_constructible<Tuple, MO, MO, ND>::value, "");
53f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(test_convertible<Tuple, MO, MO, ND>(), "");
54f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    }
55f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    {
56f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        // Same idea as above but with a nested tuple type.
57f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        typedef std::tuple<MO, ND> Tuple;
58f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        typedef std::tuple<MO, Tuple, MO, MO> NestedTuple;
59f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
60f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(!std::is_constructible<
61f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier            NestedTuple, MO, MO, MO, MO>::value, "");
62f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(std::is_constructible<
63f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier            NestedTuple, MO, Tuple, MO, MO>::value, "");
64f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    }
65f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    {
66f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        typedef std::tuple<MO, int> Tuple;
67f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        typedef std::tuple<MO, Tuple, MO, MO> NestedTuple;
68f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
69f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(std::is_constructible<
70f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier            NestedTuple, MO, MO, MO, MO>::value, "");
71f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(test_convertible<
72f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier            NestedTuple, MO, MO, MO, MO>(), "");
73f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
74f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(std::is_constructible<
75f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier            NestedTuple, MO, Tuple, MO, MO>::value, "");
76f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(test_convertible<
77f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier            NestedTuple, MO, Tuple, MO, MO>(), "");
78f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    }
79f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier}
80f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
81f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselierstd::tuple<std::string, int, std::error_code> doc_example() {
82f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier      return {"hello world", 42};
83f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier}
84f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
85f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier// Test that the example given in UsingLibcxx.rst actually works.
86f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiseliervoid test_example_from_docs() {
87f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier  auto tup = doc_example();
88f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier  assert(std::get<0>(tup) == "hello world");
89f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier  assert(std::get<1>(tup) == 42);
90f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier  assert(std::get<2>(tup) == std::error_code{});
91f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier}
92f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
93f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselierint main()
94f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier{
95f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
96f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    {
97f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        using E = MoveOnly;
98f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        using Tup = std::tuple<E, E, E>;
99f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(test_convertible<Tup, E, E, E>(), "");
100f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
101f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        Tup t = {E(0), E(1)};
102f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(test_convertible<Tup, E, E>(), "");
103f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        assert(std::get<0>(t) == 0);
104f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        assert(std::get<1>(t) == 1);
105f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        assert(std::get<2>(t) == MoveOnly());
106f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier
107f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        Tup t2 = {E(0)};
108f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        static_assert(test_convertible<Tup, E>(), "");
109f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        assert(std::get<0>(t) == 0);
110f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        assert(std::get<1>(t) == E());
111f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier        assert(std::get<2>(t) == E());
112f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    }
113f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    // Check that SFINAE is properly applied with the default reduced arity
114f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    // constructor extensions.
115f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    test_default_constructible_extension_sfinae();
116f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier    test_example_from_docs();
117f2f3637d4065238e5b93ba203635808563dfbc44Eric Fiselier}
118