//===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // template class tuple; // explicit tuple(const T&...); #include #include #include template struct never { enum { value = 0 }; }; struct NoValueCtor { NoValueCtor() : id(++count) {} NoValueCtor(NoValueCtor const & other) : id(other.id) { ++count; } // The constexpr is required to make is_constructible instantiate this template. // The explicit is needed to test-around a similar bug with is_convertible. template constexpr explicit NoValueCtor(T) { static_assert(never::value, "This should not be instantiated"); } static int count; int id; }; int NoValueCtor::count = 0; struct NoValueCtorEmpty { NoValueCtorEmpty() {} NoValueCtorEmpty(NoValueCtorEmpty const &) {} template constexpr explicit NoValueCtorEmpty(T) { static_assert(never::value, "This should not be instantiated"); } }; int main() { { std::tuple t(2); assert(std::get<0>(t) == 2); } #if _LIBCPP_STD_VER > 11 { constexpr std::tuple t(2); static_assert(std::get<0>(t) == 2, ""); } { constexpr std::tuple t; static_assert(std::get<0>(t) == 0, ""); } #endif { std::tuple t(2, 0); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); } #if _LIBCPP_STD_VER > 11 { constexpr std::tuple t(2, nullptr); static_assert(std::get<0>(t) == 2, ""); static_assert(std::get<1>(t) == nullptr, ""); } #endif { std::tuple t(2, nullptr); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); } { std::tuple t(2, nullptr, "text"); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); assert(std::get<2>(t) == "text"); } // __tuple_leaf uses is_constructible to disable its explicit converting // constructor overload __tuple_leaf(U &&). Evaluating is_constructible can cause a compile error. // This overload is evaluated when __tuple_leafs copy or move ctor is called. // This checks that is_constructible is not evaluated when U == __tuple_leaf. { std::tuple t(1, NoValueCtor(), 2, 3); assert(std::get<0>(t) == 1); assert(std::get<1>(t).id == 1); assert(std::get<2>(t) == 2); assert(std::get<3>(t) == 3); } { std::tuple t(1, NoValueCtorEmpty(), 2, 3); assert(std::get<0>(t) == 1); assert(std::get<2>(t) == 2); assert(std::get<3>(t) == 3); } // extensions { std::tuple t(2); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); assert(std::get<2>(t) == ""); } { std::tuple t(2, nullptr); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); assert(std::get<2>(t) == ""); } { std::tuple t(2, nullptr, "text"); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); assert(std::get<2>(t) == "text"); assert(std::get<3>(t) == 0.0); } }