Index: libcxx/trunk/include/tuple =================================================================== --- libcxx/trunk/include/tuple +++ libcxx/trunk/include/tuple @@ -69,6 +69,17 @@ void swap(tuple&) noexcept(AND(swap(declval(), declval())...)); }; +template +tuple(T...) -> tuple; // since C++17 +template +tuple(pair) -> tuple; // since C++17 +template +tuple(allocator_arg_t, Alloc, T...) -> tuple; // since C++17 +template +tuple(allocator_arg_t, Alloc, pair) -> tuple; // since C++17 +template +tuple(allocator_arg_t, Alloc, tuple) -> tuple; // since C++17 + inline constexpr unspecified ignore; template tuple make_tuple(T&&...); // constexpr in C++14 @@ -943,13 +954,16 @@ }; #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES -// NOTE: These are not yet standardized, but are required to simulate the -// implicit deduction guide that should be generated had libc++ declared the -// tuple-like constructors "correctly" -template -tuple(allocator_arg_t, const _Alloc&, tuple<_Args...> const&) -> tuple<_Args...>; -template -tuple(allocator_arg_t, const _Alloc&, tuple<_Args...>&&) -> tuple<_Args...>; +template +tuple(_Tp...) -> tuple<_Tp...>; +template +tuple(pair<_Tp1, _Tp2>) -> tuple<_Tp1, _Tp2>; +template +tuple(allocator_arg_t, _Alloc, _Tp...) -> tuple<_Tp...>; +template +tuple(allocator_arg_t, _Alloc, pair<_Tp1, _Tp2>) -> tuple<_Tp1, _Tp2>; +template +tuple(allocator_arg_t, _Alloc, tuple<_Tp...>) -> tuple<_Tp...>; #endif template Index: libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp =================================================================== --- libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp +++ libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp @@ -0,0 +1,201 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// 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 + +// + +// 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.hpp" + + +// 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; +} Index: libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/implicit_deduction_guides.pass.cpp =================================================================== --- libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/implicit_deduction_guides.pass.cpp +++ libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/implicit_deduction_guides.pass.cpp @@ -1,157 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 - -// 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 - -// - -// 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.hpp" - - -// Overloads -// using A = Allocator -// using AT = std::allocator_arg_t -// --------------- -// (1) tuple(const Types&...) -> tuple -// (2) explicit tuple(const Types&...) -> tuple -// (3) tuple(AT, A const&, Types const&...) -> tuple -// (4) explicit tuple(AT, A const&, Types const&...) -> tuple -// (5) tuple(tuple const& t) -> decltype(t) -// (6) tuple(tuple&& t) -> decltype(t) -// (7) tuple(AT, A const&, tuple const& t) -> decltype(t) -// (8) 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) - 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 (3) - 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 (4) - 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 (5) - using Tup = std::tuple; - const Tup t(42, nullptr); - - std::tuple t1(t); - ASSERT_SAME_TYPE(decltype(t1), Tup); - } - { // Testing (6) - using Tup = std::tuple; - std::tuple t1(Tup(nullptr, 42, 'a')); - ASSERT_SAME_TYPE(decltype(t1), Tup); - } - { // Testing (7) - using Tup = std::tuple; - const Tup t(42, nullptr); - - std::tuple t1(AT, A, t); - ASSERT_SAME_TYPE(decltype(t1), Tup); - } - { // Testing (8) - 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; -}