int main() { { hana::tuple<int> t(2); BOOST_HANA_RUNTIME_CHECK(hana::at_c<0>(t) == 2); } { constexpr hana::tuple<int> t(2); static_assert(hana::at_c<0>(t) == 2, ""); } { constexpr hana::tuple<int> t; static_assert(hana::at_c<0>(t) == 0, ""); } { constexpr hana::tuple<int, char*> t(2, nullptr); static_assert(hana::at_c<0>(t) == 2, ""); static_assert(hana::at_c<1>(t) == nullptr, ""); } { hana::tuple<int, char*> t(2, nullptr); BOOST_HANA_RUNTIME_CHECK(hana::at_c<0>(t) == 2); BOOST_HANA_RUNTIME_CHECK(hana::at_c<1>(t) == nullptr); } { hana::tuple<int, char*, std::string> t(2, nullptr, "text"); BOOST_HANA_RUNTIME_CHECK(hana::at_c<0>(t) == 2); BOOST_HANA_RUNTIME_CHECK(hana::at_c<1>(t) == nullptr); BOOST_HANA_RUNTIME_CHECK(hana::at_c<2>(t) == "text"); } { hana::tuple<int, NoValueCtor, int, int> t(1, NoValueCtor(), 2, 3); BOOST_HANA_RUNTIME_CHECK(hana::at_c<0>(t) == 1); BOOST_HANA_RUNTIME_CHECK(hana::at_c<1>(t).id == 1); BOOST_HANA_RUNTIME_CHECK(hana::at_c<2>(t) == 2); BOOST_HANA_RUNTIME_CHECK(hana::at_c<3>(t) == 3); } { hana::tuple<int, NoValueCtorEmpty, int, int> t(1, NoValueCtorEmpty(), 2, 3); BOOST_HANA_RUNTIME_CHECK(hana::at_c<0>(t) == 1); BOOST_HANA_RUNTIME_CHECK(hana::at_c<2>(t) == 2); BOOST_HANA_RUNTIME_CHECK(hana::at_c<3>(t) == 3); } { struct T { }; struct U { }; struct V { }; constexpr T t{}; constexpr U u{}; constexpr V v{}; constexpr hana::tuple<T> x1{t}; (void)x1; constexpr hana::tuple<T, U> x2{t, u}; (void)x2; constexpr hana::tuple<T, U, V> x3{t, u, v}; (void)x3; } { struct T { }; struct U { }; struct V { }; // Check for SFINAE-friendliness static_assert(!std::is_constructible< hana::tuple<T, U>, T >{}, ""); static_assert(!std::is_constructible< hana::tuple<T, U>, U, T >{}, ""); static_assert(!std::is_constructible< hana::tuple<T, U>, T, U, V >{}, ""); } // Make sure we can initialize elements with the brace-init syntax. { struct Member { }; struct Element { Member member; }; hana::tuple<Element, Element> xs{{Member()}, {Member()}}; hana::tuple<Element, Element> ys = {{Member()}, {Member()}}; (void)xs; (void)ys; } }
int main() { { std::tuple<int> t(2); assert(std::get<0>(t) == 2); } #if _LIBCPP_STD_VER > 11 { constexpr std::tuple<int> t(2); static_assert(std::get<0>(t) == 2, ""); } { constexpr std::tuple<int> t; static_assert(std::get<0>(t) == 0, ""); } #endif { std::tuple<int, char*> t(2, 0); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); } #if _LIBCPP_STD_VER > 11 { constexpr std::tuple<int, char*> t(2, nullptr); static_assert(std::get<0>(t) == 2, ""); static_assert(std::get<1>(t) == nullptr, ""); } #endif { std::tuple<int, char*> t(2, nullptr); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); } { std::tuple<int, char*, std::string> t(2, nullptr, "text"); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); assert(std::get<2>(t) == "text"); } // __tuple_leaf<T> uses is_constructible<T, U> 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<int, NoValueCtor, int, int> 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<int, NoValueCtorEmpty, int, int> 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<int, char*, std::string> t(2); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); assert(std::get<2>(t) == ""); } { std::tuple<int, char*, std::string> t(2, nullptr); assert(std::get<0>(t) == 2); assert(std::get<1>(t) == nullptr); assert(std::get<2>(t) == ""); } { std::tuple<int, char*, std::string, double> 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); } }