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 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10
11 // <utility>
12
13 // template <class T1, class T2> struct pair
14 // template <class U1, class U2>
15 // constexpr explicit(see below) pair(pair<U1, U2>& p);
16
17 #include <cassert>
18 #include <utility>
19
20 #include "copy_move_types.h"
21 #include "test_macros.h"
22
23 // Constraints:
24 // is_constructible_v<T1, decltype(get<0>(FWD(p)))> is true and
25 // is_constructible_v<T2, decltype(get<1>(FWD(p)))> is true.
26 struct X {};
27 struct Y {};
28 struct NotConvertibleToXorY {};
29
30 // clang-format off
31 static_assert( std::is_constructible_v<std::pair<X, Y>, std::pair<X, Y>&>);
32 static_assert(!std::is_constructible_v<std::pair<X, Y>, std::pair<NotConvertibleToXorY, Y>&>);
33 static_assert(!std::is_constructible_v<std::pair<X, Y>, std::pair<X, NotConvertibleToXorY>&>);
34 static_assert(!std::is_constructible_v<std::pair<X, Y>, std::pair<NotConvertibleToXorY, NotConvertibleToXorY>&>);
35
36 // The expression inside explicit is equivalent to:
37 // !is_convertible_v<decltype(get<0>(FWD(p))), first_type> ||
38 // !is_convertible_v<decltype(get<1>(FWD(p))), second_type>.
39 static_assert( std::is_convertible_v<std::pair<X, Y>&, std::pair<ConvertibleFrom<X>, ConvertibleFrom<Y>>>);
40 static_assert(!std::is_convertible_v<std::pair<X, Y>&, std::pair<ConvertibleFrom<X>, ExplicitConstructibleFrom<Y>>>);
41 static_assert(!std::is_convertible_v<std::pair<X, Y>&, std::pair<ExplicitConstructibleFrom<X>, ConvertibleFrom<Y>>>);
42 static_assert(!std::is_convertible_v<std::pair<X, Y>&, std::pair<ExplicitConstructibleFrom<X>, ExplicitConstructibleFrom<Y>>>);
43 // clang-format on
44
test()45 constexpr bool test() {
46 // use case in zip. Init pair<T&, U&> from pair<T, U>&
47 {
48 std::pair<int, int> p1{1, 2};
49 std::pair<int&, int&> p2{p1};
50 assert(&(p2.first) == &(p1.first));
51 assert(&(p2.second) == &(p1.second));
52 }
53
54 // test implicit conversions.
55 {
56 std::pair<MutableCopy, int> p1{1, 2};
57 std::pair<ConvertibleFrom<MutableCopy>, ConvertibleFrom<int>> p2 = p1;
58 assert(p2.first.v.val == 1);
59 assert(p2.second.v == 2);
60 }
61
62 // test explicit conversions.
63 {
64 std::pair<MutableCopy, int> p1{1, 2};
65 std::pair<ExplicitConstructibleFrom<MutableCopy>, ExplicitConstructibleFrom<int>> p2{p1};
66 assert(p2.first.v.val == 1);
67 assert(p2.second.v == 2);
68 }
69
70 // test correct constructors of underlying types are called
71 {
72 std::pair<TracedCopyMove, TracedCopyMove> p1{};
73 std::pair<ConvertibleFrom<TracedCopyMove>, ConvertibleFrom<TracedCopyMove>> p2{p1};
74 assert(nonConstCopyCtrCalled(p2.first.v));
75 assert(nonConstCopyCtrCalled(p2.second.v));
76 }
77
78 return true;
79 }
80
main(int,char **)81 int main(int, char**) {
82 test();
83 static_assert(test());
84 return 0;
85 }
86