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 
23 template <class ...>
24 struct never {
25     enum { value = 0 };
26 };
27 
28 struct NoValueCtor
29 {
NoValueCtorNoValueCtor30     NoValueCtor() : id(++count) {}
NoValueCtorNoValueCtor31     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>
NoValueCtorNoValueCtor36     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 
43 int NoValueCtor::count = 0;
44 
45 
46 struct NoValueCtorEmpty
47 {
NoValueCtorEmptyNoValueCtorEmpty48     NoValueCtorEmpty() {}
NoValueCtorEmptyNoValueCtorEmpty49     NoValueCtorEmpty(NoValueCtorEmpty const &) {}
50 
51     template <class T>
NoValueCtorEmptyNoValueCtorEmpty52     constexpr explicit NoValueCtorEmpty(T)
53     { static_assert(never<T>::value, "This should not be instantiated"); }
54 };
55 
main()56 int 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