xref: /llvm-project/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_ref.pass.cpp (revision da876a157d7985f7f8de906180fa5ad7b685724a)
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