//===----------------------------------------------------------------------===// // // 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&...); // UNSUPPORTED: c++98, c++03 #include #include #include #include "test_macros.h" 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"); } }; struct ImplicitCopy { explicit ImplicitCopy(int) {} ImplicitCopy(ImplicitCopy const&) {} }; // Test that tuple(std::allocator_arg, Alloc, Types const&...) allows implicit // copy conversions in return value expressions. std::tuple testImplicitCopy1() { ImplicitCopy i(42); return {i}; } std::tuple testImplicitCopy2() { const ImplicitCopy i(42); return {i}; } std::tuple testImplicitCopy3() { const ImplicitCopy i(42); return i; } int main() { { // check that the literal '0' can implicitly initialize a stored pointer. std::tuple t = 0; assert(std::get<0>(t) == nullptr); } { std::tuple t(2); assert(std::get<0>(t) == 2); } #if TEST_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 TEST_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 #ifdef _LIBCPP_VERSION { 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); } #endif }