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 { 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 43 int NoValueCtor::count = 0; 44 45 46 struct 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 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