//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03, c++11, c++14 // UNSUPPORTED: libcpp-no-deduction-guides // UNSUPPORTED: apple-clang-9 // GCC's implementation of class template deduction is still immature and runs // into issues with libc++. However GCC accepts this code when compiling // against libstdc++. // XFAIL: gcc-5, gcc-6, gcc-7 // // Test that the constructors offered by std::tuple are formulated // so they're compatible with implicit deduction guides, or if that's not // possible that they provide explicit guides to make it work. #include #include #include #include "test_macros.h" #include "archetypes.h" // Overloads // using A = Allocator // using AT = std::allocator_arg_t // --------------- // (1) tuple(const Types&...) -> tuple // (2) tuple(pair) -> tuple; // (3) explicit tuple(const Types&...) -> tuple // (4) tuple(AT, A const&, Types const&...) -> tuple // (5) explicit tuple(AT, A const&, Types const&...) -> tuple // (6) tuple(AT, A, pair) -> tuple // (7) tuple(tuple const& t) -> decltype(t) // (8) tuple(tuple&& t) -> decltype(t) // (9) tuple(AT, A const&, tuple const& t) -> decltype(t) // (10) tuple(AT, A const&, tuple&& t) -> decltype(t) void test_primary_template() { const std::allocator A; const auto AT = std::allocator_arg; { // Testing (1) int x = 101; std::tuple t1(42); ASSERT_SAME_TYPE(decltype(t1), std::tuple); std::tuple t2(x, 0.0, nullptr); ASSERT_SAME_TYPE(decltype(t2), std::tuple); } { // Testing (2) std::pair p1(1, 'c'); std::tuple t1(p1); ASSERT_SAME_TYPE(decltype(t1), std::tuple); std::pair> p2(1, std::tuple('c', 3l, nullptr)); std::tuple t2(p2); ASSERT_SAME_TYPE(decltype(t2), std::tuple>); int i = 3; std::pair, char> p3(std::ref(i), 'c'); std::tuple t3(p3); ASSERT_SAME_TYPE(decltype(t3), std::tuple, char>); std::pair p4(i, 'c'); std::tuple t4(p4); ASSERT_SAME_TYPE(decltype(t4), std::tuple); std::tuple t5(std::pair(1, 'c')); ASSERT_SAME_TYPE(decltype(t5), std::tuple); } { // Testing (3) using T = ExplicitTestTypes::TestType; static_assert(!std::is_convertible::value, ""); std::tuple t1(T{}); ASSERT_SAME_TYPE(decltype(t1), std::tuple); const T v{}; std::tuple t2(T{}, 101l, v); ASSERT_SAME_TYPE(decltype(t2), std::tuple); } { // Testing (4) int x = 101; std::tuple t1(AT, A, 42); ASSERT_SAME_TYPE(decltype(t1), std::tuple); std::tuple t2(AT, A, 42, 0.0, x); ASSERT_SAME_TYPE(decltype(t2), std::tuple); } { // Testing (5) using T = ExplicitTestTypes::TestType; static_assert(!std::is_convertible::value, ""); std::tuple t1(AT, A, T{}); ASSERT_SAME_TYPE(decltype(t1), std::tuple); const T v{}; std::tuple t2(AT, A, T{}, 101l, v); ASSERT_SAME_TYPE(decltype(t2), std::tuple); } { // Testing (6) std::pair p1(1, 'c'); std::tuple t1(AT, A, p1); ASSERT_SAME_TYPE(decltype(t1), std::tuple); std::pair> p2(1, std::tuple('c', 3l, nullptr)); std::tuple t2(AT, A, p2); ASSERT_SAME_TYPE(decltype(t2), std::tuple>); int i = 3; std::pair, char> p3(std::ref(i), 'c'); std::tuple t3(AT, A, p3); ASSERT_SAME_TYPE(decltype(t3), std::tuple, char>); std::pair p4(i, 'c'); std::tuple t4(AT, A, p4); ASSERT_SAME_TYPE(decltype(t4), std::tuple); std::tuple t5(AT, A, std::pair(1, 'c')); ASSERT_SAME_TYPE(decltype(t5), std::tuple); } { // Testing (7) using Tup = std::tuple; const Tup t(42, nullptr); std::tuple t1(t); ASSERT_SAME_TYPE(decltype(t1), Tup); } { // Testing (8) using Tup = std::tuple; std::tuple t1(Tup(nullptr, 42, 'a')); ASSERT_SAME_TYPE(decltype(t1), Tup); } { // Testing (9) using Tup = std::tuple; const Tup t(42, nullptr); std::tuple t1(AT, A, t); ASSERT_SAME_TYPE(decltype(t1), Tup); } { // Testing (10) using Tup = std::tuple; std::tuple t1(AT, A, Tup(nullptr, 42, 'a')); ASSERT_SAME_TYPE(decltype(t1), Tup); } } // Overloads // using A = Allocator // using AT = std::allocator_arg_t // --------------- // (1) tuple() -> tuple<> // (2) tuple(AT, A const&) -> tuple<> // (3) tuple(tuple const&) -> tuple<> // (4) tuple(tuple&&) -> tuple<> // (5) tuple(AT, A const&, tuple const&) -> tuple<> // (6) tuple(AT, A const&, tuple&&) -> tuple<> void test_empty_specialization() { std::allocator A; const auto AT = std::allocator_arg; { // Testing (1) std::tuple t1{}; ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); } { // Testing (2) std::tuple t1{AT, A}; ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); } { // Testing (3) const std::tuple<> t{}; std::tuple t1(t); ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); } { // Testing (4) std::tuple t1(std::tuple<>{}); ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); } { // Testing (5) const std::tuple<> t{}; std::tuple t1(AT, A, t); ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); } { // Testing (6) std::tuple t1(AT, A, std::tuple<>{}); ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); } } int main(int, char**) { test_primary_template(); test_empty_specialization(); return 0; }