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// <tuple>
11
12// template <class... Types> class tuple;
13
14// explicit tuple(const T&...);
15
16// UNSUPPORTED: c++98, c++03
17
18#include <tuple>
19#include <string>
20#include <cassert>
21
22
23template <class ...>
24struct never {
25    enum { value = 0 };
26};
27
28struct NoValueCtor
29{
30    NoValueCtor() : id(++count) {}
31    NoValueCtor(NoValueCtor const & other) : id(other.id) { ++count; }
32
33    // The constexpr is required to make is_constructible instantiate this template.
34    // The explicit is needed to test-around a similar bug with is_convertible.
35    template <class T>
36    constexpr explicit NoValueCtor(T)
37    { static_assert(never<T>::value, "This should not be instantiated"); }
38
39    static int count;
40    int id;
41};
42
43int NoValueCtor::count = 0;
44
45
46struct NoValueCtorEmpty
47{
48    NoValueCtorEmpty() {}
49    NoValueCtorEmpty(NoValueCtorEmpty const &) {}
50
51    template <class T>
52    constexpr explicit NoValueCtorEmpty(T)
53    { static_assert(never<T>::value, "This should not be instantiated"); }
54};
55
56int main()
57{
58    {
59        std::tuple<int> t(2);
60        assert(std::get<0>(t) == 2);
61    }
62#if _LIBCPP_STD_VER > 11
63    {
64        constexpr std::tuple<int> t(2);
65        static_assert(std::get<0>(t) == 2, "");
66    }
67    {
68        constexpr std::tuple<int> t;
69        static_assert(std::get<0>(t) == 0, "");
70    }
71#endif
72    {
73        std::tuple<int, char*> t(2, 0);
74        assert(std::get<0>(t) == 2);
75        assert(std::get<1>(t) == nullptr);
76    }
77#if _LIBCPP_STD_VER > 11
78    {
79        constexpr std::tuple<int, char*> t(2, nullptr);
80        static_assert(std::get<0>(t) == 2, "");
81        static_assert(std::get<1>(t) == nullptr, "");
82    }
83#endif
84    {
85        std::tuple<int, char*> t(2, nullptr);
86        assert(std::get<0>(t) == 2);
87        assert(std::get<1>(t) == nullptr);
88    }
89    {
90        std::tuple<int, char*, std::string> t(2, nullptr, "text");
91        assert(std::get<0>(t) == 2);
92        assert(std::get<1>(t) == nullptr);
93        assert(std::get<2>(t) == "text");
94    }
95    // __tuple_leaf<T> uses is_constructible<T, U> to disable its explicit converting
96    // constructor overload __tuple_leaf(U &&). Evaluating is_constructible can cause a compile error.
97    // This overload is evaluated when __tuple_leafs copy or move ctor is called.
98    // This checks that is_constructible is not evaluated when U == __tuple_leaf.
99    {
100        std::tuple<int, NoValueCtor, int, int> t(1, NoValueCtor(), 2, 3);
101        assert(std::get<0>(t) == 1);
102        assert(std::get<1>(t).id == 1);
103        assert(std::get<2>(t) == 2);
104        assert(std::get<3>(t) == 3);
105    }
106    {
107        std::tuple<int, NoValueCtorEmpty, int, int> t(1, NoValueCtorEmpty(), 2, 3);
108        assert(std::get<0>(t) == 1);
109        assert(std::get<2>(t) == 2);
110        assert(std::get<3>(t) == 3);
111    }
112    // extensions
113    {
114        std::tuple<int, char*, std::string> t(2);
115        assert(std::get<0>(t) == 2);
116        assert(std::get<1>(t) == nullptr);
117        assert(std::get<2>(t) == "");
118    }
119    {
120        std::tuple<int, char*, std::string> t(2, nullptr);
121        assert(std::get<0>(t) == 2);
122        assert(std::get<1>(t) == nullptr);
123        assert(std::get<2>(t) == "");
124    }
125    {
126        std::tuple<int, char*, std::string, double> t(2, nullptr, "text");
127        assert(std::get<0>(t) == 2);
128        assert(std::get<1>(t) == nullptr);
129        assert(std::get<2>(t) == "text");
130        assert(std::get<3>(t) == 0.0);
131    }
132}
133