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