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