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 U1, class U2>
13 // constexpr explicit(see below) tuple<Types...>::tuple(pair<U1, U2>& u);
14
15 // Constraints:
16 // - sizeof...(Types) is 2 and
17 // - is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and
18 // - is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
19
20 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
21
22 #include <cassert>
23 #include <tuple>
24 #include <utility>
25
26 #include "copy_move_types.h"
27
28 // test constraints
29 // sizeof...(Types) == 2
30 static_assert(std::is_constructible_v<std::tuple<MutableCopy, int>, std::pair<MutableCopy, int>&>);
31
32 static_assert(!std::is_constructible_v<std::tuple<MutableCopy>, std::pair<MutableCopy, int>&>);
33
34 static_assert(!std::is_constructible_v<std::tuple<MutableCopy, int, int>, std::pair<MutableCopy, int>&>);
35
36 // test constraints
37 // is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and
38 // is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
39 static_assert(std::is_constructible_v<std::tuple<int, int>, std::pair<int, int>&>);
40
41 static_assert(!std::is_constructible_v<std::tuple<NoConstructorFromInt, int>, std::pair<int, int>&>);
42
43 static_assert(!std::is_constructible_v<std::tuple<int, NoConstructorFromInt>, std::pair<int, int>&>);
44
45 static_assert(!std::is_constructible_v< std::tuple<NoConstructorFromInt, NoConstructorFromInt>, std::pair<int, int>&>);
46
47 // test: The expression inside explicit is equivalent to:
48 // !is_convertible_v<decltype(get<0>(FWD(u))), T0> ||
49 // !is_convertible_v<decltype(get<1>(FWD(u))), T1>
50 static_assert(std::is_convertible_v<std::pair<MutableCopy, MutableCopy>&,
51 std::tuple<ConvertibleFrom<MutableCopy>, ConvertibleFrom<MutableCopy>>>);
52
53 static_assert(!std::is_convertible_v<std::pair<MutableCopy, MutableCopy>&,
54 std::tuple<ExplicitConstructibleFrom<MutableCopy>, ConvertibleFrom<MutableCopy>>>);
55
56 static_assert(!std::is_convertible_v<std::pair<MutableCopy, MutableCopy>&,
57 std::tuple<ConvertibleFrom<MutableCopy>, ExplicitConstructibleFrom<MutableCopy>>>);
58
test()59 constexpr bool test() {
60 // test implicit conversions.
61 {
62 std::pair<MutableCopy, int> p{1, 2};
63 std::tuple<ConvertibleFrom<MutableCopy>, ConvertibleFrom<int>> t = p;
64 assert(std::get<0>(t).v.val == 1);
65 assert(std::get<1>(t).v == 2);
66 }
67
68 // test explicit conversions.
69 {
70 std::pair<MutableCopy, int> p{1, 2};
71 std::tuple<ExplicitConstructibleFrom<MutableCopy>, ExplicitConstructibleFrom<int>> t{p};
72 assert(std::get<0>(t).v.val == 1);
73 assert(std::get<1>(t).v == 2);
74 }
75
76 // non const overload should be called
77 {
78 std::pair<TracedCopyMove, TracedCopyMove> p;
79 std::tuple<ConvertibleFrom<TracedCopyMove>, TracedCopyMove> t = p;
80 assert(nonConstCopyCtrCalled(std::get<0>(t).v));
81 assert(nonConstCopyCtrCalled(std::get<1>(t)));
82 }
83
84 return true;
85 }
86
main(int,char **)87 int main(int, char**) {
88 test();
89 static_assert(test());
90
91 return 0;
92 }
93