| //===----------------------------------------------------------------------===// |
| // |
| // 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 |
| |
| // <tuple> |
| |
| // 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 <tuple> |
| #include <memory> |
| #include <cassert> |
| |
| #include "test_macros.h" |
| #include "archetypes.h" |
| |
| |
| // Overloads |
| // using A = Allocator |
| // using AT = std::allocator_arg_t |
| // --------------- |
| // (1) tuple(const Types&...) -> tuple<Types...> |
| // (2) tuple(pair<T1, T2>) -> tuple<T1, T2>; |
| // (3) explicit tuple(const Types&...) -> tuple<Types...> |
| // (4) tuple(AT, A const&, Types const&...) -> tuple<Types...> |
| // (5) explicit tuple(AT, A const&, Types const&...) -> tuple<Types...> |
| // (6) tuple(AT, A, pair<T1, T2>) -> tuple<T1, T2> |
| // (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<int> A; |
| const auto AT = std::allocator_arg; |
| { // Testing (1) |
| int x = 101; |
| std::tuple t1(42); |
| ASSERT_SAME_TYPE(decltype(t1), std::tuple<int>); |
| std::tuple t2(x, 0.0, nullptr); |
| ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, double, decltype(nullptr)>); |
| } |
| { // Testing (2) |
| std::pair<int, char> p1(1, 'c'); |
| std::tuple t1(p1); |
| ASSERT_SAME_TYPE(decltype(t1), std::tuple<int, char>); |
| |
| std::pair<int, std::tuple<char, long, void*>> p2(1, std::tuple<char, long, void*>('c', 3l, nullptr)); |
| std::tuple t2(p2); |
| ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, std::tuple<char, long, void*>>); |
| |
| int i = 3; |
| std::pair<std::reference_wrapper<int>, char> p3(std::ref(i), 'c'); |
| std::tuple t3(p3); |
| ASSERT_SAME_TYPE(decltype(t3), std::tuple<std::reference_wrapper<int>, char>); |
| |
| std::pair<int&, char> p4(i, 'c'); |
| std::tuple t4(p4); |
| ASSERT_SAME_TYPE(decltype(t4), std::tuple<int&, char>); |
| |
| std::tuple t5(std::pair<int, char>(1, 'c')); |
| ASSERT_SAME_TYPE(decltype(t5), std::tuple<int, char>); |
| } |
| { // Testing (3) |
| using T = ExplicitTestTypes::TestType; |
| static_assert(!std::is_convertible<T const&, T>::value, ""); |
| |
| std::tuple t1(T{}); |
| ASSERT_SAME_TYPE(decltype(t1), std::tuple<T>); |
| |
| const T v{}; |
| std::tuple t2(T{}, 101l, v); |
| ASSERT_SAME_TYPE(decltype(t2), std::tuple<T, long, T>); |
| } |
| { // Testing (4) |
| int x = 101; |
| std::tuple t1(AT, A, 42); |
| ASSERT_SAME_TYPE(decltype(t1), std::tuple<int>); |
| |
| std::tuple t2(AT, A, 42, 0.0, x); |
| ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, double, int>); |
| } |
| { // Testing (5) |
| using T = ExplicitTestTypes::TestType; |
| static_assert(!std::is_convertible<T const&, T>::value, ""); |
| |
| std::tuple t1(AT, A, T{}); |
| ASSERT_SAME_TYPE(decltype(t1), std::tuple<T>); |
| |
| const T v{}; |
| std::tuple t2(AT, A, T{}, 101l, v); |
| ASSERT_SAME_TYPE(decltype(t2), std::tuple<T, long, T>); |
| } |
| { // Testing (6) |
| std::pair<int, char> p1(1, 'c'); |
| std::tuple t1(AT, A, p1); |
| ASSERT_SAME_TYPE(decltype(t1), std::tuple<int, char>); |
| |
| std::pair<int, std::tuple<char, long, void*>> p2(1, std::tuple<char, long, void*>('c', 3l, nullptr)); |
| std::tuple t2(AT, A, p2); |
| ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, std::tuple<char, long, void*>>); |
| |
| int i = 3; |
| std::pair<std::reference_wrapper<int>, char> p3(std::ref(i), 'c'); |
| std::tuple t3(AT, A, p3); |
| ASSERT_SAME_TYPE(decltype(t3), std::tuple<std::reference_wrapper<int>, char>); |
| |
| std::pair<int&, char> p4(i, 'c'); |
| std::tuple t4(AT, A, p4); |
| ASSERT_SAME_TYPE(decltype(t4), std::tuple<int&, char>); |
| |
| std::tuple t5(AT, A, std::pair<int, char>(1, 'c')); |
| ASSERT_SAME_TYPE(decltype(t5), std::tuple<int, char>); |
| } |
| { // Testing (7) |
| using Tup = std::tuple<int, decltype(nullptr)>; |
| const Tup t(42, nullptr); |
| |
| std::tuple t1(t); |
| ASSERT_SAME_TYPE(decltype(t1), Tup); |
| } |
| { // Testing (8) |
| using Tup = std::tuple<void*, unsigned, char>; |
| std::tuple t1(Tup(nullptr, 42, 'a')); |
| ASSERT_SAME_TYPE(decltype(t1), Tup); |
| } |
| { // Testing (9) |
| using Tup = std::tuple<int, decltype(nullptr)>; |
| const Tup t(42, nullptr); |
| |
| std::tuple t1(AT, A, t); |
| ASSERT_SAME_TYPE(decltype(t1), Tup); |
| } |
| { // Testing (10) |
| using Tup = std::tuple<void*, unsigned, char>; |
| 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<int> 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; |
| } |