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