1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // <tuple>
10
11 // template <class... Types>
12 // template <class Alloc, class U1, class U2>
13 // constexpr explicit(see below)
14 // tuple<Types...>::tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&
15 // u);
16
17 // Constraints:
18 // - sizeof...(Types) is 2 and
19 // - is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and
20 // - is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
21
22 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
23
24 #include <cassert>
25 #include <tuple>
26 #include <utility>
27
28 #include "convert_types.h"
29 #include "test_allocator.h"
30
31 // test constraints
32 // sizeof...(Types) == 2
33 static_assert(std::is_constructible_v<std::tuple<MutableCopy, int>, std::allocator_arg_t, test_allocator<int>,
34 std::pair<MutableCopy, int>&>);
35
36 static_assert(!std::is_constructible_v< std::tuple<MutableCopy>, std::allocator_arg_t, test_allocator<int>,
37 std::pair<MutableCopy, int>&>);
38
39 static_assert(!std::is_constructible_v< std::tuple<MutableCopy, int, int>, std::allocator_arg_t, test_allocator<int>,
40 std::pair<MutableCopy, int>&>);
41
42 // test constraints
43 // is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and
44 // is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
45 static_assert(
46 std::is_constructible_v<std::tuple<int, int>, std::allocator_arg_t, test_allocator<int>, std::pair<int, int>&>);
47
48 static_assert(!std::is_constructible_v< std::tuple<NoConstructorFromInt, int>, std::allocator_arg_t,
49 test_allocator<int>, std::pair<int, int>&>);
50
51 static_assert(!std::is_constructible_v< std::tuple<int, NoConstructorFromInt>, std::allocator_arg_t,
52 test_allocator<int>, std::pair<int, int>&>);
53
54 static_assert(!std::is_constructible_v< std::tuple<NoConstructorFromInt, NoConstructorFromInt>, std::allocator_arg_t,
55 test_allocator<int>, std::pair<int, int>&>);
56
57 // test: The expression inside explicit is equivalent to:
58 // !is_convertible_v<decltype(get<0>(FWD(u))), T0> ||
59 // !is_convertible_v<decltype(get<1>(FWD(u))), T1>
60 static_assert(ImplicitlyConstructible<std::tuple<ConvertibleFrom<MutableCopy>, ConvertibleFrom<MutableCopy>>,
61 std::allocator_arg_t, test_allocator<int>, std::pair<MutableCopy, MutableCopy>&>);
62
63 static_assert(
64 !ImplicitlyConstructible<std::tuple<ConvertibleFrom<MutableCopy>, ExplicitConstructibleFrom<MutableCopy>>,
65 std::allocator_arg_t, test_allocator<int>, std::pair<MutableCopy, MutableCopy>&>);
66
67 static_assert(
68 !ImplicitlyConstructible<std::tuple<ExplicitConstructibleFrom<MutableCopy>, ConvertibleFrom<MutableCopy>>,
69 std::allocator_arg_t, test_allocator<int>, std::pair<MutableCopy, MutableCopy>&>);
70
test()71 constexpr bool test() {
72 // test implicit conversions.
73 {
74 std::pair<MutableCopy, int> p{1, 2};
75 std::tuple<ConvertibleFrom<MutableCopy>, ConvertibleFrom<int>> t = {std::allocator_arg, test_allocator<int>{}, p};
76 assert(std::get<0>(t).v.val == 1);
77 assert(std::get<1>(t).v == 2);
78 assert(std::get<0>(t).alloc_constructed);
79 assert(std::get<1>(t).alloc_constructed);
80 }
81
82 // test explicit conversions.
83 {
84 std::pair<MutableCopy, int> p{1, 2};
85 std::tuple<ExplicitConstructibleFrom<MutableCopy>, ExplicitConstructibleFrom<int>> t{std::allocator_arg,
86 test_allocator<int>{}, p};
87 assert(std::get<0>(t).v.val == 1);
88 assert(std::get<1>(t).v == 2);
89 assert(std::get<0>(t).alloc_constructed);
90 assert(std::get<1>(t).alloc_constructed);
91 }
92
93 // non const overload should be called
94 {
95 std::pair<TracedCopyMove, TracedCopyMove> p;
96 std::tuple<ConvertibleFrom<TracedCopyMove>, TracedCopyMove> t = {std::allocator_arg, test_allocator<int>{}, p};
97 assert(nonConstCopyCtrCalled(std::get<0>(t).v));
98 assert(nonConstCopyCtrCalled(std::get<1>(t)));
99 assert(std::get<0>(t).alloc_constructed);
100 assert(std::get<1>(t).alloc_constructed);
101 }
102
103 return true;
104 }
105
main(int,char **)106 int main(int, char**) {
107 test();
108 static_assert(test());
109
110 return 0;
111 }
112